summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:14:06 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:14:06 +0000
commiteee068778cb28ecf3c14e1bf843a95547d72c42d (patch)
tree0e07b30ddc5ea579d682d5dbe57998200d1c9ab7 /tests
parentInitial commit. (diff)
downloadgnupg2-eee068778cb28ecf3c14e1bf843a95547d72c42d.tar.xz
gnupg2-eee068778cb28ecf3c14e1bf843a95547d72c42d.zip
Adding upstream version 2.2.40.upstream/2.2.40upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/ChangeLog-2011152
-rw-r--r--tests/Makefile.am77
-rw-r--r--tests/Makefile.in935
-rw-r--r--tests/asschk.c1094
-rw-r--r--tests/fake-pinentries/README.txt38
-rwxr-xr-xtests/fake-pinentries/fake-pinentry.php27
-rwxr-xr-xtests/fake-pinentries/fake-pinentry.pl27
-rwxr-xr-xtests/fake-pinentries/fake-pinentry.py30
-rwxr-xr-xtests/fake-pinentries/fake-pinentry.sh33
-rw-r--r--tests/gpgme/Makefile.am57
-rw-r--r--tests/gpgme/Makefile.in628
-rw-r--r--tests/gpgme/all-tests.scm86
-rw-r--r--tests/gpgme/gpgme-defs.scm129
-rw-r--r--tests/gpgme/run-tests.scm20
-rw-r--r--tests/gpgme/setup.scm35
-rw-r--r--tests/gpgme/wrap.scm66
-rw-r--r--tests/gpgscm/LICENSE.TinySCHEME31
-rw-r--r--tests/gpgscm/Makefile.am64
-rw-r--r--tests/gpgscm/Makefile.in882
-rw-r--r--tests/gpgscm/Manual.txt444
-rw-r--r--tests/gpgscm/ffi-private.h148
-rw-r--r--tests/gpgscm/ffi.c1470
-rw-r--r--tests/gpgscm/ffi.h30
-rw-r--r--tests/gpgscm/ffi.scm51
-rw-r--r--tests/gpgscm/gnupg.scm49
-rw-r--r--tests/gpgscm/init.scm823
-rw-r--r--tests/gpgscm/lib.scm307
-rw-r--r--tests/gpgscm/main.c362
-rw-r--r--tests/gpgscm/makefile.scm76
-rw-r--r--tests/gpgscm/opdefines.h205
-rw-r--r--tests/gpgscm/private.h26
-rw-r--r--tests/gpgscm/repl.scm69
-rw-r--r--tests/gpgscm/scheme-config.h32
-rw-r--r--tests/gpgscm/scheme-private.h274
-rw-r--r--tests/gpgscm/scheme.c6043
-rw-r--r--tests/gpgscm/scheme.h290
-rw-r--r--tests/gpgscm/small-integers.h847
-rw-r--r--tests/gpgscm/t-child.c74
-rw-r--r--tests/gpgscm/t-child.scm118
-rw-r--r--tests/gpgscm/tests.scm886
-rw-r--r--tests/gpgscm/time.scm42
-rw-r--r--tests/gpgscm/xml.scm142
-rw-r--r--tests/gpgsm/32100C27173EF6E9C4E9A25D3D69F86D37A4F93910
-rw-r--r--tests/gpgsm/Makefile.am75
-rw-r--r--tests/gpgsm/Makefile.in648
-rw-r--r--tests/gpgsm/all-tests.scm43
-rw-r--r--tests/gpgsm/cert_dfn_pca01.derbin0 -> 1224 bytes
-rw-r--r--tests/gpgsm/cert_dfn_pca15.derbin0 -> 1560 bytes
-rw-r--r--tests/gpgsm/cert_g10code_test1.derbin0 -> 793 bytes
-rw-r--r--tests/gpgsm/decrypt.scm30
-rw-r--r--tests/gpgsm/encrypt.scm39
-rw-r--r--tests/gpgsm/export.scm32
-rw-r--r--tests/gpgsm/gpgsm-defs.scm104
-rw-r--r--tests/gpgsm/import.scm53
-rw-r--r--tests/gpgsm/plain-1.cms.asc33
-rw-r--r--tests/gpgsm/plain-2.cms.asc43
-rw-r--r--tests/gpgsm/plain-3.cms.asc11
-rw-r--r--tests/gpgsm/plain-large.cms.asc4213
-rw-r--r--tests/gpgsm/run-tests.scm39
-rw-r--r--tests/gpgsm/setup.scm28
-rw-r--r--tests/gpgsm/sign.scm35
-rw-r--r--tests/gpgsm/verify.scm65
-rwxr-xr-xtests/inittests100
-rw-r--r--tests/migrations/Makefile.am66
-rw-r--r--tests/migrations/Makefile.in638
-rw-r--r--tests/migrations/all-tests.scm35
-rw-r--r--tests/migrations/common.scm61
-rwxr-xr-xtests/migrations/extended-pkf.scm38
-rw-r--r--tests/migrations/extended-pkf.tar.asc220
-rwxr-xr-xtests/migrations/from-classic.scm61
-rw-r--r--tests/migrations/from-classic.tar.asc209
-rwxr-xr-xtests/migrations/issue2276.scm32
-rw-r--r--tests/migrations/issue2276.tar.asc326
-rw-r--r--tests/migrations/run-tests.scm27
-rw-r--r--tests/migrations/setup.scm20
-rw-r--r--tests/openpgp/4gb-packet.ascbin0 -> 4983 bytes
-rwxr-xr-xtests/openpgp/4gb-packet.scm29
-rw-r--r--tests/openpgp/ChangeLog-2011424
-rw-r--r--tests/openpgp/Makefile.am290
-rw-r--r--tests/openpgp/Makefile.in940
-rw-r--r--tests/openpgp/README257
-rw-r--r--tests/openpgp/all-tests.scm78
-rwxr-xr-xtests/openpgp/armdetach.scm32
-rwxr-xr-xtests/openpgp/armdetachm.scm36
-rwxr-xr-xtests/openpgp/armencrypt.scm31
-rwxr-xr-xtests/openpgp/armencryptp.scm32
-rwxr-xr-xtests/openpgp/armor.scm767
-rwxr-xr-xtests/openpgp/armsignencrypt.scm31
-rwxr-xr-xtests/openpgp/armsigs.scm31
-rw-r--r--tests/openpgp/bug1223-bogus.asc21
-rw-r--r--tests/openpgp/bug1223-good.asc20
-rw-r--r--tests/openpgp/bug537-test.data.asc960
-rw-r--r--tests/openpgp/bug894-test.asc565
-rwxr-xr-xtests/openpgp/clearsig.scm108
-rwxr-xr-xtests/openpgp/compression.scm36
-rwxr-xr-xtests/openpgp/conventional-mdc.scm50
-rwxr-xr-xtests/openpgp/conventional.scm49
-rwxr-xr-xtests/openpgp/decrypt-dsa.scm30
-rwxr-xr-xtests/openpgp/decrypt-multifile.scm47
-rwxr-xr-xtests/openpgp/decrypt-session-key.scm45
-rwxr-xr-xtests/openpgp/decrypt-unwrap-verify.scm41
-rwxr-xr-xtests/openpgp/decrypt.scm30
-rwxr-xr-xtests/openpgp/default-key.scm77
-rw-r--r--tests/openpgp/defs.scm509
-rwxr-xr-xtests/openpgp/delete-keys.scm109
-rwxr-xr-xtests/openpgp/detach.scm32
-rwxr-xr-xtests/openpgp/detachm.scm36
-rwxr-xr-xtests/openpgp/ecc.scm249
-rwxr-xr-xtests/openpgp/enarmor.scm31
-rwxr-xr-xtests/openpgp/encrypt-dsa.scm46
-rwxr-xr-xtests/openpgp/encrypt-multifile.scm39
-rwxr-xr-xtests/openpgp/encrypt.scm61
-rwxr-xr-xtests/openpgp/encryptp.scm32
-rwxr-xr-xtests/openpgp/export.scm100
-rw-r--r--tests/openpgp/fake-pinentry.c318
-rwxr-xr-xtests/openpgp/genkey1024.scm53
-rw-r--r--tests/openpgp/gpgconf.scm47
-rwxr-xr-xtests/openpgp/gpgtar.scm94
-rwxr-xr-xtests/openpgp/gpgv-forged-keyring.scm68
-rwxr-xr-xtests/openpgp/gpgv.scm75
-rw-r--r--tests/openpgp/import-revocation-certificate.scm37
-rwxr-xr-xtests/openpgp/import.scm61
-rwxr-xr-xtests/openpgp/issue2015.scm31
-rwxr-xr-xtests/openpgp/issue2346.scm28
-rwxr-xr-xtests/openpgp/issue2417.scm32
-rwxr-xr-xtests/openpgp/issue2419.scm29
-rw-r--r--tests/openpgp/issue2929.scm32
-rwxr-xr-xtests/openpgp/issue2941.scm34
-rw-r--r--tests/openpgp/key-selection.scm83
-rw-r--r--tests/openpgp/key-selection/0.asc30
-rw-r--r--tests/openpgp/key-selection/1.asc30
-rw-r--r--tests/openpgp/key-selection/2.asc30
-rw-r--r--tests/openpgp/key-selection/3.asc43
-rw-r--r--tests/openpgp/key-selection/4.asc18
-rwxr-xr-xtests/openpgp/mds.scm69
-rwxr-xr-xtests/openpgp/mkdemodirs41
-rwxr-xr-xtests/openpgp/multisig.scm169
-rw-r--r--tests/openpgp/plain-1-pgp.asc27
-rw-r--r--tests/openpgp/plain-1.asc26
-rw-r--r--tests/openpgp/plain-1o.asc28
-rw-r--r--tests/openpgp/plain-2.asc31
-rw-r--r--tests/openpgp/plain-2o.asc36
-rw-r--r--tests/openpgp/plain-3.asc13
-rw-r--r--tests/openpgp/plain-3o.asc10
-rw-r--r--tests/openpgp/plain-large.asc1332
-rw-r--r--tests/openpgp/plain-largeo.asc4205
-rw-r--r--tests/openpgp/privkeys/00FE67F28A52A8AA08FFAED20AF832DA916D1985.asc17
-rw-r--r--tests/openpgp/privkeys/0D6F6AD4C4C803B25470F9104E9F4E6A4CA64255.asc12
-rw-r--r--tests/openpgp/privkeys/0DD40284FF992CD24DC4AAC367037E066FCEE26A.asc27
-rw-r--r--tests/openpgp/privkeys/13FDB8809B17C5547779F9D205C45F47CE0217CE.asc17
-rw-r--r--tests/openpgp/privkeys/1DF48228FEFF3EC2481B106E0ACA8C465C662CC5.asc23
-rw-r--r--tests/openpgp/privkeys/1E28F20E41B54C2D1234D896096495FF57E08D18.asc9
-rw-r--r--tests/openpgp/privkeys/2BC997C0B8691D41D29A4EC81CCBCF08454E4961.asc31
-rw-r--r--tests/openpgp/privkeys/343D8AF79796EE107D645A2787A9D9252F924E6F.asc17
-rw-r--r--tests/openpgp/privkeys/3C9D5ECA70130C2DBB1FC6AC0076BEEEC197716F.asc31
-rw-r--r--tests/openpgp/privkeys/449E644892C951A37525654730DD32C202079926.asc10
-rw-r--r--tests/openpgp/privkeys/4DF9172D6FF428C97A0E9AA96F03E8BCE3B2F188.asc31
-rw-r--r--tests/openpgp/privkeys/50B2D4FA4122C212611048BC5FC31BD44393626E.asc21
-rw-r--r--tests/openpgp/privkeys/58FFE844087634E62440224908BDE44BEA7EB730.asc31
-rw-r--r--tests/openpgp/privkeys/6E6B7ED0BD4425018FFC54F3921D5467A3AE00EB.asc31
-rw-r--r--tests/openpgp/privkeys/76F7E2B35832976B50A27A282D9B87E44577EB66.asc21
-rw-r--r--tests/openpgp/privkeys/7E201E28B6FEB2927B321F443205F4724EBE637E.asc18
-rw-r--r--tests/openpgp/privkeys/8B5ABF3EF9EB8D96B91A0B8C2C4401C91C834C34.asc14
-rw-r--r--tests/openpgp/privkeys/9D7CD8F53F2F14C3E2177D1E9D1D11F39513A4A4.asc10
-rw-r--r--tests/openpgp/privkeys/A0747D5F9425E6664F4FFBEED20FBCA79FDED2BD.asc20
-rw-r--r--tests/openpgp/privkeys/A2832820DC9F40751BDCD375BB0945BA33EC6B4C.asc17
-rw-r--r--tests/openpgp/privkeys/ADE710D74409777B7729A7653373D820F67892E0.asc17
-rw-r--r--tests/openpgp/privkeys/B2BAA7144303DF19BB6FDE23781DD3FDD97918D4.asc31
-rw-r--r--tests/openpgp/privkeys/C6A6390E9388CDBAD71EAEA698233FE5E04F001E.asc27
-rw-r--r--tests/openpgp/privkeys/C905D0AB6AE9655C5A35975939997BBF3325D6DD.asc13
-rw-r--r--tests/openpgp/privkeys/CEFC51AF91F68A2904FBFF62C4F075A4785B803F.asc17
-rw-r--r--tests/openpgp/privkeys/CF60965BF51F67CF80DECE853E0D2D343468571D.asc31
-rw-r--r--tests/openpgp/privkeys/D69102E0F5AC6B6DB8E4D16DA8E18CF46D88CAE3.asc27
-rw-r--r--tests/openpgp/privkeys/DF00E361D34F80868D06879AC21D7A7D4E4FAD76.asc31
-rw-r--r--tests/openpgp/privkeys/EB33B687EB8581AB64D04852A54453E85F3DF62D.asc10
-rw-r--r--tests/openpgp/privkeys/FD692BD59D6640A84C8422573D469F84F3B98E53.asc15
-rw-r--r--tests/openpgp/pubdemo.asc566
-rw-r--r--tests/openpgp/pubring.asc720
-rw-r--r--tests/openpgp/pubring.pkr.asc28
-rwxr-xr-xtests/openpgp/quick-key-manipulation.scm228
-rw-r--r--tests/openpgp/run-tests.scm42
-rw-r--r--tests/openpgp/samplekeys/E657FB607BB4F21C90BB6651BC067AF28BC90111.asc45
-rw-r--r--tests/openpgp/samplekeys/README33
-rw-r--r--tests/openpgp/samplekeys/authenticate-only.pub.asc31
-rw-r--r--tests/openpgp/samplekeys/authenticate-only.sec.asc60
-rw-r--r--tests/openpgp/samplekeys/dda252ebb8ebe1af-1.asc29
-rw-r--r--tests/openpgp/samplekeys/dda252ebb8ebe1af-2.asc29
-rw-r--r--tests/openpgp/samplekeys/e2e-p256-1-clr.asc37
-rw-r--r--tests/openpgp/samplekeys/e2e-p256-1-prt.asc39
-rw-r--r--tests/openpgp/samplekeys/ecc-sample-1-pub.asc22
-rw-r--r--tests/openpgp/samplekeys/ecc-sample-1-sec.asc25
-rw-r--r--tests/openpgp/samplekeys/ecc-sample-2-pub.asc25
-rw-r--r--tests/openpgp/samplekeys/ecc-sample-2-sec.asc22
-rw-r--r--tests/openpgp/samplekeys/ecc-sample-3-pub.asc28
-rw-r--r--tests/openpgp/samplekeys/ecc-sample-3-sec.asc24
-rw-r--r--tests/openpgp/samplekeys/ed25519-cv25519-sample-1.asc21
-rw-r--r--tests/openpgp/samplekeys/eddsa-sample-1-pub.asc15
-rw-r--r--tests/openpgp/samplekeys/eddsa-sample-1-sec.asc19
-rw-r--r--tests/openpgp/samplekeys/issue2346.gpg57
-rw-r--r--tests/openpgp/samplekeys/rsa-rsa-sample-1.asc38
-rw-r--r--tests/openpgp/samplekeys/silent-running.asc120
-rw-r--r--tests/openpgp/samplekeys/ssh-dsa.key12
-rw-r--r--tests/openpgp/samplekeys/ssh-ecdsa.key5
-rw-r--r--tests/openpgp/samplekeys/ssh-ed25519.key7
-rw-r--r--tests/openpgp/samplekeys/ssh-rsa.key27
-rw-r--r--tests/openpgp/samplekeys/whats-new-in-2.1.asc128
-rw-r--r--tests/openpgp/samplemsgs/clearsig-1-key-1.asc17
-rw-r--r--tests/openpgp/samplemsgs/clearsig-2-keys-1.asc20
-rw-r--r--tests/openpgp/samplemsgs/clearsig-2-keys-2.asc20
-rw-r--r--tests/openpgp/samplemsgs/enc-1-key-1.asc9
-rw-r--r--tests/openpgp/samplemsgs/enc-1-key-2.asc16
-rw-r--r--tests/openpgp/samplemsgs/enc-2-keys-1.asc17
-rw-r--r--tests/openpgp/samplemsgs/enc-2-keys-2.asc16
-rw-r--r--tests/openpgp/samplemsgs/enc-2-keys-hh-1.asc20
-rw-r--r--tests/openpgp/samplemsgs/enc-2-keys-hr-1.asc29
-rw-r--r--tests/openpgp/samplemsgs/enc-2-keys-rh-1.asc21
-rw-r--r--tests/openpgp/samplemsgs/encsig-2-2-keys-3.asc35
-rw-r--r--tests/openpgp/samplemsgs/encsig-2-2-keys-4.asc33
-rw-r--r--tests/openpgp/samplemsgs/encsig-2-keys-1.asc18
-rw-r--r--tests/openpgp/samplemsgs/encsig-2-keys-2.asc18
-rw-r--r--tests/openpgp/samplemsgs/encsig-2-keys-3.asc23
-rw-r--r--tests/openpgp/samplemsgs/encsig-2-keys-4.asc23
-rw-r--r--tests/openpgp/samplemsgs/encz0-1-key-1.asc12
-rw-r--r--tests/openpgp/samplemsgs/encz0-1-key-2.asc13
-rw-r--r--tests/openpgp/samplemsgs/issue2419.asc7
-rw-r--r--tests/openpgp/samplemsgs/revoke-2D727CC768697734.asc8
-rw-r--r--tests/openpgp/samplemsgs/sig-1-key-1.asc8
-rw-r--r--tests/openpgp/samplemsgs/sig-1-key-2.asc12
-rw-r--r--tests/openpgp/samplemsgs/sig-2-keys-1.asc15
-rw-r--r--tests/openpgp/samplemsgs/sig-2-keys-2.asc15
-rw-r--r--tests/openpgp/samplemsgs/signed-1-key-1.asc15
-rw-r--r--tests/openpgp/samplemsgs/signed-1-key-2.asc12
-rw-r--r--tests/openpgp/samplemsgs/signed-2-keys-1.asc17
-rw-r--r--tests/openpgp/samplemsgs/signed-2-keys-2.asc24
-rwxr-xr-xtests/openpgp/seat.scm31
-rw-r--r--tests/openpgp/secdemo.asc737
-rw-r--r--tests/openpgp/secring.asc73
-rw-r--r--tests/openpgp/secring.skr.asc27
-rwxr-xr-xtests/openpgp/setup.scm49
-rw-r--r--tests/openpgp/shell.scm53
-rwxr-xr-xtests/openpgp/signdemokey16
-rw-r--r--tests/openpgp/signed-messages.scm281
-rwxr-xr-xtests/openpgp/signencrypt-dsa.scm49
-rwxr-xr-xtests/openpgp/signencrypt.scm41
-rwxr-xr-xtests/openpgp/sigs-dsa.scm44
-rwxr-xr-xtests/openpgp/sigs.scm51
-rwxr-xr-xtests/openpgp/ssh-export.scm52
-rwxr-xr-xtests/openpgp/ssh-import.scm101
-rwxr-xr-xtests/openpgp/tofu.scm420
-rw-r--r--tests/openpgp/tofu/conflicting/1C005AF3-1.txtbin0 -> 342 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/1C005AF3-2.txtbin0 -> 338 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/1C005AF3-3.txtbin0 -> 339 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/1C005AF3-4.txtbin0 -> 338 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/1C005AF3-5.txtbin0 -> 339 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/1C005AF3-secret.gpgbin0 -> 2537 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/1C005AF3.gpgbin0 -> 1235 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/B662E42F-1.txtbin0 -> 340 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/B662E42F-2.txtbin0 -> 339 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/B662E42F-3.txtbin0 -> 342 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/B662E42F-4.txtbin0 -> 340 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/B662E42F-5.txt1
-rw-r--r--tests/openpgp/tofu/conflicting/B662E42F-secret.gpgbin0 -> 2537 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/B662E42F.gpgbin0 -> 1235 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/BE04EB2B-1.txtbin0 -> 340 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/BE04EB2B-2.txtbin0 -> 342 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/BE04EB2B-3.txtbin0 -> 340 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/BE04EB2B-4.txtbin0 -> 342 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/BE04EB2B-5.txtbin0 -> 340 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/BE04EB2B-secret.gpgbin0 -> 2537 bytes
-rw-r--r--tests/openpgp/tofu/conflicting/BE04EB2B.gpgbin0 -> 1235 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/871C2247-1.gpgbin0 -> 1173 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/871C2247-1.txtbin0 -> 321 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/871C2247-2.gpgbin0 -> 1460 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/871C2247-2.txtbin0 -> 333 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/871C2247-3.gpgbin0 -> 1800 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/871C2247-3.txtbin0 -> 334 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/871C2247-4.gpgbin0 -> 2087 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/871C2247-secret.gpgbin0 -> 2475 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/EC38277E-1.gpgbin0 -> 1171 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/EC38277E-1.txtbin0 -> 321 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/EC38277E-2.gpgbin0 -> 1458 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/EC38277E-2.txtbin0 -> 334 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/EC38277E-3.txtbin0 -> 334 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/EC38277E-secret.gpgbin0 -> 2473 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/README79
-rwxr-xr-xtests/openpgp/trust-pgp-1.scm76
-rwxr-xr-xtests/openpgp/trust-pgp-2.scm39
-rwxr-xr-xtests/openpgp/trust-pgp-3.scm31
-rwxr-xr-xtests/openpgp/trust-pgp-4.scm37
-rw-r--r--tests/openpgp/trust-pgp/alice.sec.asc11
-rw-r--r--tests/openpgp/trust-pgp/bobby.sec.asc11
-rw-r--r--tests/openpgp/trust-pgp/carol.sec.asc11
-rw-r--r--tests/openpgp/trust-pgp/common.scm66
-rw-r--r--tests/openpgp/trust-pgp/david.sec.asc11
-rw-r--r--tests/openpgp/trust-pgp/frank.sec.asc11
-rw-r--r--tests/openpgp/trust-pgp/grace.sec.asc11
-rw-r--r--tests/openpgp/trust-pgp/heidi.sec.asc11
-rw-r--r--tests/openpgp/trust-pgp/scenario1.asc75
-rw-r--r--tests/openpgp/trust-pgp/scenario2.asc70
-rw-r--r--tests/openpgp/trust-pgp/scenario3.asc58
-rw-r--r--tests/openpgp/trust-pgp/scenario4.asc84
-rwxr-xr-xtests/openpgp/use-exact-key.scm69
-rwxr-xr-xtests/openpgp/verify-multifile.scm41
-rwxr-xr-xtests/openpgp/verify.scm87
-rwxr-xr-xtests/openpgp/version.scm25
-rw-r--r--tests/pkits/ChangeLog-201175
-rw-r--r--tests/pkits/Makefile.am75
-rw-r--r--tests/pkits/Makefile.in695
-rw-r--r--tests/pkits/README37
-rwxr-xr-xtests/pkits/basic-certificate-revocation31
-rwxr-xr-xtests/pkits/certificate-policies31
-rw-r--r--tests/pkits/common.sh275
-rwxr-xr-xtests/pkits/delta-crls31
-rwxr-xr-xtests/pkits/distribution-points31
-rwxr-xr-xtests/pkits/import-all-certs58
-rw-r--r--tests/pkits/import-all-certs.data471
-rwxr-xr-xtests/pkits/inhibit-any-policy31
-rwxr-xr-xtests/pkits/inhibit-policy-mapping31
-rwxr-xr-xtests/pkits/inittests109
-rwxr-xr-xtests/pkits/key-usage28
-rwxr-xr-xtests/pkits/name-constraints31
-rwxr-xr-xtests/pkits/policy-mappings31
-rwxr-xr-xtests/pkits/private-certificate-extensions31
-rwxr-xr-xtests/pkits/require-explicit-policy31
-rwxr-xr-xtests/pkits/runtest4
-rwxr-xr-xtests/pkits/signature-verification167
-rwxr-xr-xtests/pkits/validate-all-certs59
-rwxr-xr-xtests/pkits/validity-periods218
-rwxr-xr-xtests/pkits/verifying-basic-constraints31
-rwxr-xr-xtests/pkits/verifying-name-chaining31
-rwxr-xr-xtests/pkits/verifying-paths-self-issued31
-rw-r--r--tests/run-tests.scm44
-rwxr-xr-xtests/runtest3
-rw-r--r--tests/samplekeys/32100C27173EF6E9C4E9A25D3D69F86D37A4F939.key18
-rw-r--r--tests/samplekeys/68A638998DFABAC510EA645CE34F9686B2EDF7EA.key10
-rw-r--r--tests/samplekeys/cert_g10code_pete1.pem24
-rw-r--r--tests/samplekeys/cert_g10code_test1.pem19
-rw-r--r--tests/samplekeys/cert_g10code_theo1.pem40
-rw-r--r--tests/samplekeys/steed-self-signing-nonthority.pem54
-rw-r--r--tests/sm-sign+verify73
-rw-r--r--tests/sm-verify114
-rw-r--r--tests/text-1.dsig.pem27
-rw-r--r--tests/text-1.osig-bad.pem45
-rw-r--r--tests/text-1.osig.pem48
-rw-r--r--tests/text-1.txt17
-rw-r--r--tests/text-2.osig-bad.pem28
-rw-r--r--tests/text-2.osig.pem29
-rw-r--r--tests/text-2.txt2
-rw-r--r--tests/text-3.txt2
349 files changed, 47827 insertions, 0 deletions
diff --git a/tests/ChangeLog-2011 b/tests/ChangeLog-2011
new file mode 100644
index 0000000..972dbf5
--- /dev/null
+++ b/tests/ChangeLog-2011
@@ -0,0 +1,152 @@
+2011-12-01 Werner Koch <wk@g10code.com>
+
+ NB: ChangeLog files are no longer manually maintained. Starting
+ on December 1st, 2011 we put change information only in the GIT
+ commit log, and generate a top-level ChangeLog file from logs at
+ "make dist". See doc/HACKING for details.
+
+2011-09-20 Jim Meyering <meyering@redhat.com>
+
+ avoid use of free'd pointer
+ * asschk.c (set_type_var): Set var->value to NULL after freeing it,
+ to avoid subsequent use of freed pointer.
+
+2009-10-13 Werner Koch <wk@g10code.com>
+
+ * asschk.c (die): Replace this vararg macro by C-89 compliant
+ macros die_0, die_1, die_2 and die 3. Change all callers.
+ Reported by Nelson H. F. Beebe.
+
+2009-02-19 Werner Koch <wk@g10code.com>
+
+ * Makefile.am (TESTS_ENVIRONMENT): Use /bin/pwd.
+ * inittests: Ditto. Fixes bug#1001.
+
+2008-10-20 Werner Koch <wk@g10code.com>
+
+ * asschk.c (cmd_echo): Mark unused arg.
+ (cmd_send, cmd_expect_ok, cmd_expect_err, cmd_pipeserver)
+ (cmd_quit_if, cmd_fail_if): Ditto.
+
+2008-09-29 Werner Koch <wk@g10code.com>
+
+ * Makefile.am (TESTS): Remove tests.
+
+2008-02-19 Werner Koch <wk@g10code.com>
+
+ * Makefile.am: Always run pkits tests.
+
+2008-01-17 Werner Koch <wk@g10code.com>
+
+ * asschk.c (read_assuan): Use __func__ instead of __FUNCTION__.
+
+2006-11-05 Werner Koch <wk@g10code.com>
+
+ * asschk.c (read_assuan): Minor cleanups.
+
+2006-09-06 Marcus Brinkmann <marcus@g10code.de>
+
+ * Makefile.am (openpgp): New variable.
+ (SUBDIRS): Conditionalize openpgp on RUN_GPG_TESTS.
+
+2006-08-21 Werner Koch <wk@g10code.com>
+
+ * Makefile.am (SUBDIRS): New.
+ * openpgp/: New.
+
+2006-06-08 Marcus Brinkmann <marcus@g10code.de>
+
+ * asschk.c (__func__) [__STDC_VERSION__ < 199901L && __GNUC__ >= 2]:
+ Define macro to __FUNCTION__.
+ (die): Use __func__ instead of __FUNCTION__.
+
+2005-10-07 Marcus Brinkmann <marcus@g10code.de>
+
+ * Makefile.am (TESTS_ENVIRONMENT): Remove LD_LIBRARY_PATH hack.
+ It's the responsibility of the person building the software to set
+ it properly.
+
+2004-09-30 Werner Koch <wk@g10code.com>
+
+ * Makefile.am (SUBDIRS): Remove pkits until the copyright issues
+ have been cleared.
+
+2004-08-16 Werner Koch <wk@g10code.de>
+
+ * Makefile.am: Descend into the new pkits directory
+
+2004-02-20 Werner Koch <wk@gnupg.org>
+
+ * Makefile.am: Reset GPG_AGENT_INFO here
+ * runtest: and not anymore here.
+
+2002-12-04 Werner Koch <wk@gnupg.org>
+
+ * inittests (gpgsm.conf): Fake system time.
+
+2002-10-31 Neal H. Walfield <neal@g10code.de>
+
+ * Makefile.am (inittests.stamp): Do not set LD_LIBRARY_PATH here.
+ (TESTS_ENVIRONMENT): Do it here. And also frob $(LIBGCRYPT_LIBS)
+ and $(PTH_LIBS).
+
+2002-10-31 Neal H. Walfield <neal@g10code.de>
+
+ * asschk.c (die): New macro.
+ (read_assuan): If in verbose mode, dump the string that was read.
+ (write_assuan): Be more verbose on failure.
+
+2002-09-04 Neal H. Walfield <neal@g10code.de>
+
+ * Makefile.am (inittests.stamp): Do not set LD_LIBRARY_PATH, but
+ rather prepend it. Be more robust and prefer printf over echo -n.
+
+2002-09-04 Marcus Brinkmann <marcus@g10code.de>
+
+ * asschk.c (start_server): Close the parent's file descriptors in
+ the child.
+ (read_assuan): Variable NREAD removed. Cut off the received line
+ currectly if more than one line was read.
+
+2002-09-03 Neal H. Walfield <neal@g10code.de>
+
+ * Makefile.am (inittests.stamp): Construct an LD_LIBRARY_PATH from
+ LDFLAGS.
+
+2002-08-09 Werner Koch <wk@gnupg.org>
+
+ * asschk.c (cmd_getenv): New.
+ (expand_line): Allow / as variable name delimiter.
+ * sm-sign+verify, sm-verify: Use $srcdir so that a VPATH build works.
+
+ * Makefile.am: Fixes for make dist.
+ * samplekets/Makefile.am: New.
+
+2002-08-08 Werner Koch <wk@gnupg.org>
+
+ * asschk.c: Added some new features.
+ * runtest, inittests: New.
+ * text-1.txt, text-2.txt, text-3.txt: New.
+ * text-1.osig.pem, text-1.dsig.pem, text-1.osig-bad.pem: New.
+ * text-2.osig.pem, text-2.osig-bad.pem: New.
+ * samplekeys : New directory
+ * sm-verify, sm-sign+verify: The first test scripts.
+
+2002-08-06 Werner Koch <wk@gnupg.org>
+
+ * Makefile.am, asschk.c: New.
+
+
+ Copyright 2002 Free Software Foundation, Inc.
+
+ This file is free software; as a special exception the author gives
+ unlimited permission to copy and/or distribute it, with or without
+ modifications, as long as this notice is preserved.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+Local Variables:
+buffer-read-only: t
+End:
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 0000000..65978ae
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,77 @@
+# Makefile.am
+# Copyright (C) 2002 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+
+## Process this file with automake to produce Makefile.in
+
+SUBDIRS = gpgscm openpgp migrations gpgsm gpgme pkits .
+
+GPGSM = ../sm/gpgsm
+
+# Note that we need to use /bin/pwd so that we don't get into trouble
+# if the shell used for inittests would uses an internal version of
+# pwd which handles symlinks differently.
+TESTS_ENVIRONMENT = GNUPGHOME=`/bin/pwd` GPG_AGENT_INFO= LC_ALL=C \
+ GPGSM="$(GPGSM)" "$(srcdir)/runtest"
+
+testscripts = sm-sign+verify sm-verify
+
+EXTRA_DIST = runtest inittests $(testscripts) ChangeLog-2011 \
+ text-1.txt text-2.txt text-3.txt \
+ text-1.osig.pem text-1.dsig.pem text-1.osig-bad.pem \
+ text-2.osig.pem text-2.osig-bad.pem \
+ fake-pinentries/README.txt \
+ fake-pinentries/fake-pinentry.php \
+ fake-pinentries/fake-pinentry.pl \
+ fake-pinentries/fake-pinentry.py \
+ fake-pinentries/fake-pinentry.sh \
+ samplekeys/steed-self-signing-nonthority.pem \
+ samplekeys/68A638998DFABAC510EA645CE34F9686B2EDF7EA.key \
+ samplekeys/32100C27173EF6E9C4E9A25D3D69F86D37A4F939.key \
+ samplekeys/cert_g10code_pete1.pem \
+ samplekeys/cert_g10code_test1.pem \
+ samplekeys/cert_g10code_theo1.pem \
+ run-tests.scm
+
+# We used to run $(testscripts) here but these asschk scripts are not
+# completely reliable in all environments and thus we better disable
+# them. The tests are anyway way too minimal. We will eventually
+# write new tests based on gpg-connect-agent which has a full fledged
+# script language and thus makes it far easier to write tests than to
+# use that low-level asschk stuff.
+TESTS =
+
+CLEANFILES = inittests.stamp x y y z out err \
+ *.lock .\#lk*
+
+DISTCLEANFILES = pubring.kbx~ random_seed
+
+if !HAVE_W32_SYSTEM
+noinst_PROGRAMS = asschk
+endif
+
+asschk_SOURCES = asschk.c
+
+
+all-local: inittests.stamp
+
+clean-local:
+ srcdir=$(srcdir) $(TESTS_ENVIRONMENT) $(srcdir)/inittests --clean
+
+inittests.stamp: inittests
+ srcdir=$(srcdir) $(TESTS_ENVIRONMENT) $(srcdir)/inittests
+ echo timestamp >./inittests.stamp
diff --git a/tests/Makefile.in b/tests/Makefile.in
new file mode 100644
index 0000000..a70f0d0
--- /dev/null
+++ b/tests/Makefile.in
@@ -0,0 +1,935 @@
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am
+# Copyright (C) 2002 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+TESTS =
+@HAVE_W32_SYSTEM_FALSE@noinst_PROGRAMS = asschk$(EXEEXT)
+subdir = tests
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/autobuild.m4 \
+ $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/ksba.m4 \
+ $(top_srcdir)/m4/lcmessage.m4 $(top_srcdir)/m4/ldap.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libassuan.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/npth.m4 $(top_srcdir)/m4/ntbtls.m4 \
+ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \
+ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/readline.m4 \
+ $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \
+ $(top_srcdir)/m4/tar-ustar.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+PROGRAMS = $(noinst_PROGRAMS)
+am_asschk_OBJECTS = asschk.$(OBJEXT)
+asschk_OBJECTS = $(am_asschk_OBJECTS)
+asschk_LDADD = $(LDADD)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/asschk.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(asschk_SOURCES)
+DIST_SOURCES = $(asschk_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+ ctags-recursive dvi-recursive html-recursive info-recursive \
+ install-data-recursive install-dvi-recursive \
+ install-exec-recursive install-html-recursive \
+ install-info-recursive install-pdf-recursive \
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ distdir distdir-am
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ fi; \
+}
+DIST_SUBDIRS = $(SUBDIRS)
+am__DIST_COMMON = $(srcdir)/Makefile.in \
+ $(top_srcdir)/build-aux/depcomp \
+ $(top_srcdir)/build-aux/mkinstalldirs
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+AWK_HEX_NUMBER_OPTION = @AWK_HEX_NUMBER_OPTION@
+BUILD_FILEVERSION = @BUILD_FILEVERSION@
+BUILD_HOSTNAME = @BUILD_HOSTNAME@
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+BUILD_REVISION = @BUILD_REVISION@
+BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
+BUILD_VERSION = @BUILD_VERSION@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DL_LIBS = @DL_LIBS@
+DNSLIBS = @DNSLIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENCFS = @ENCFS@
+EXEEXT = @EXEEXT@
+FUSERMOUNT = @FUSERMOUNT@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNUPG_AGENT_PGM = @GNUPG_AGENT_PGM@
+GNUPG_DIRMNGR_LDAP_PGM = @GNUPG_DIRMNGR_LDAP_PGM@
+GNUPG_DIRMNGR_PGM = @GNUPG_DIRMNGR_PGM@
+GNUPG_PINENTRY_PGM = @GNUPG_PINENTRY_PGM@
+GNUPG_PROTECT_TOOL_PGM = @GNUPG_PROTECT_TOOL_PGM@
+GNUPG_SCDAEMON_PGM = @GNUPG_SCDAEMON_PGM@
+GPGKEYS_LDAP = @GPGKEYS_LDAP@
+GPGRT_CONFIG = @GPGRT_CONFIG@
+GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
+GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
+GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
+GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
+GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+KSBA_CFLAGS = @KSBA_CFLAGS@
+KSBA_CONFIG = @KSBA_CONFIG@
+KSBA_LIBS = @KSBA_LIBS@
+LBER_LIBS = @LBER_LIBS@
+LDAPLIBS = @LDAPLIBS@
+LDAP_CPPFLAGS = @LDAP_CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
+LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
+LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@
+LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBREADLINE = @LIBREADLINE@
+LIBS = @LIBS@
+LIBUSB_CPPFLAGS = @LIBUSB_CPPFLAGS@
+LIBUSB_LIBS = @LIBUSB_LIBS@
+LIBUTIL_LIBS = @LIBUTIL_LIBS@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NETLIBS = @NETLIBS@
+NPTH_CFLAGS = @NPTH_CFLAGS@
+NPTH_CONFIG = @NPTH_CONFIG@
+NPTH_LIBS = @NPTH_LIBS@
+NTBTLS_CFLAGS = @NTBTLS_CFLAGS@
+NTBTLS_CONFIG = @NTBTLS_CONFIG@
+NTBTLS_LIBS = @NTBTLS_LIBS@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_GT = @PACKAGE_GT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SENDMAIL = @SENDMAIL@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHRED = @SHRED@
+SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
+SQLITE3_LIBS = @SQLITE3_LIBS@
+STRIP = @STRIP@
+SYSROOT = @SYSROOT@
+SYS_SOCKET_H = @SYS_SOCKET_H@
+TAR = @TAR@
+USE_C99_CFLAGS = @USE_C99_CFLAGS@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+W32SOCKLIBS = @W32SOCKLIBS@
+WINDRES = @WINDRES@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+YAT2M = @YAT2M@
+ZLIBS = @ZLIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = gpgscm openpgp migrations gpgsm gpgme pkits .
+GPGSM = ../sm/gpgsm
+
+# Note that we need to use /bin/pwd so that we don't get into trouble
+# if the shell used for inittests would uses an internal version of
+# pwd which handles symlinks differently.
+TESTS_ENVIRONMENT = GNUPGHOME=`/bin/pwd` GPG_AGENT_INFO= LC_ALL=C \
+ GPGSM="$(GPGSM)" "$(srcdir)/runtest"
+
+testscripts = sm-sign+verify sm-verify
+EXTRA_DIST = runtest inittests $(testscripts) ChangeLog-2011 \
+ text-1.txt text-2.txt text-3.txt \
+ text-1.osig.pem text-1.dsig.pem text-1.osig-bad.pem \
+ text-2.osig.pem text-2.osig-bad.pem \
+ fake-pinentries/README.txt \
+ fake-pinentries/fake-pinentry.php \
+ fake-pinentries/fake-pinentry.pl \
+ fake-pinentries/fake-pinentry.py \
+ fake-pinentries/fake-pinentry.sh \
+ samplekeys/steed-self-signing-nonthority.pem \
+ samplekeys/68A638998DFABAC510EA645CE34F9686B2EDF7EA.key \
+ samplekeys/32100C27173EF6E9C4E9A25D3D69F86D37A4F939.key \
+ samplekeys/cert_g10code_pete1.pem \
+ samplekeys/cert_g10code_test1.pem \
+ samplekeys/cert_g10code_theo1.pem \
+ run-tests.scm
+
+CLEANFILES = inittests.stamp x y y z out err \
+ *.lock .\#lk*
+
+DISTCLEANFILES = pubring.kbx~ random_seed
+asschk_SOURCES = asschk.c
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu tests/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+
+asschk$(EXEEXT): $(asschk_OBJECTS) $(asschk_DEPENDENCIES) $(EXTRA_asschk_DEPENDENCIES)
+ @rm -f asschk$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(asschk_OBJECTS) $(asschk_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asschk.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+ @fail=; \
+ if $(am__make_keepgoing); then \
+ failcom='fail=yes'; \
+ else \
+ failcom='exit 1'; \
+ fi; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ $(am__tty_colors); \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=XPASS; \
+ ;; \
+ *) \
+ col=$$grn; res=PASS; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xfail=`expr $$xfail + 1`; \
+ col=$$lgn; res=XFAIL; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=FAIL; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ col=$$blu; res=SKIP; \
+ fi; \
+ echo "$${col}$$res$${std}: $$tst"; \
+ done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="$$All$$all $$tests passed"; \
+ else \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all $$tests failed"; \
+ else \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ if test "$$failed" -eq 0; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ fi; \
+ echo "$${col}$$dashes$${std}"; \
+ echo "$${col}$$banner$${std}"; \
+ test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
+ test -z "$$report" || echo "$${col}$$report$${std}"; \
+ echo "$${col}$$dashes$${std}"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-recursive
+all-am: Makefile $(PROGRAMS) all-local
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-local clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f ./$(DEPDIR)/asschk.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f ./$(DEPDIR)/asschk.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(am__recursive_targets) check-am install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am all-local \
+ am--depfiles check check-TESTS check-am clean clean-generic \
+ clean-local clean-noinstPROGRAMS cscopelist-am ctags ctags-am \
+ distclean distclean-compile distclean-generic distclean-tags \
+ distdir dvi dvi-am html html-am info info-am install \
+ install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
+ ps ps-am tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+all-local: inittests.stamp
+
+clean-local:
+ srcdir=$(srcdir) $(TESTS_ENVIRONMENT) $(srcdir)/inittests --clean
+
+inittests.stamp: inittests
+ srcdir=$(srcdir) $(TESTS_ENVIRONMENT) $(srcdir)/inittests
+ echo timestamp >./inittests.stamp
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tests/asschk.c b/tests/asschk.c
new file mode 100644
index 0000000..65828e5
--- /dev/null
+++ b/tests/asschk.c
@@ -0,0 +1,1094 @@
+/* asschk.c - Assuan Server Checker
+ * Copyright (C) 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+/* This is a simple stand-alone Assuan server test program. We don't
+ want to use the assuan library because we don't want to hide errors
+ in that library.
+
+ The script language is line based. Empty lines or lines containing
+ only white spaces are ignored, line with a hash sign as first non
+ white space character are treated as comments.
+
+ A simple macro mechanism is implemnted. Macros are expanded before
+ a line is processed but after comment processing. Macros are only
+ expanded once and non existing macros expand to the empty string.
+ A macro is dereferenced by prefixing its name with a dollar sign;
+ the end of the name is currently indicated by a white space, a
+ dollar sign or a slash. To use a dollor sign verbatim, double it.
+
+ A macro is assigned by prefixing a statement with the macro name
+ and an equal sign. The value is assigned verbatim if it does not
+ resemble a command, otherwise the return value of the command will
+ get assigned. The command "let" may be used to assign values
+ unambigiously and it should be used if the value starts with a
+ letter.
+
+ Conditions are not yes implemented except for a simple evaluation
+ which yields false for an empty string or the string "0". The
+ result may be negated by prefixing with a '!'.
+
+ The general syntax of a command is:
+
+ [<name> =] <statement> [<args>]
+
+ If NAME is not specifed but the statement returns a value it is
+ assigned to the name "?" so that it can be referenced using "$?".
+ The following commands are implemented:
+
+ let <value>
+ Return VALUE.
+
+ echo <value>
+ Print VALUE.
+
+ openfile <filename>
+ Open file FILENAME for read access and return the file descriptor.
+
+ createfile <filename>
+ Create file FILENAME, open for write access and return the file
+ descriptor.
+
+ pipeserver <program>
+ Connect to the Assuan server PROGRAM.
+
+ send <line>
+ Send LINE to the server.
+
+ expect-ok
+ Expect an OK response from the server. Status and data out put
+ is ignored.
+
+ expect-err
+ Expect an ERR response from the server. Status and data out put
+ is ignored.
+
+ count-status <code>
+ Initialize the assigned variable to 0 and assign it as an counter for
+ status code CODE. This command must be called with an assignment.
+
+ quit
+ Terminate the process.
+
+ quit-if <condition>
+ Terminate the process if CONDITION evaluates to true.
+
+ fail-if <condition>
+ Terminate the process with an exit code of 1 if CONDITION
+ evaluates to true.
+
+ cmpfiles <first> <second>
+ Returns true when the content of the files FIRST and SECOND match.
+
+ getenv <name>
+ Return the value of the environment variable NAME.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
+# define ATTR_PRINTF(f,a) __attribute__ ((format (printf,f,a)))
+#else
+# define ATTR_PRINTF(f,a)
+#endif
+
+#if __STDC_VERSION__ < 199901L
+# if __GNUC__ >= 2 && !defined (__func__)
+# define __func__ __FUNCTION__
+# else
+/* Let's try our luck here. Some systems may provide __func__ without
+ providing __STDC_VERSION__ 199901L. */
+# if 0
+# define __func__ "<unknown>"
+# endif
+# endif
+#endif
+
+#define spacep(p) (*(p) == ' ' || *(p) == '\t')
+
+#define MAX_LINELEN 2048
+
+typedef enum {
+ LINE_OK = 0,
+ LINE_ERR,
+ LINE_STAT,
+ LINE_DATA,
+ LINE_END,
+} LINETYPE;
+
+typedef enum {
+ VARTYPE_SIMPLE = 0,
+ VARTYPE_FD,
+ VARTYPE_COUNTER
+} VARTYPE;
+
+
+struct variable_s {
+ struct variable_s *next;
+ VARTYPE type;
+ unsigned int count;
+ char *value;
+ char name[1];
+};
+typedef struct variable_s *VARIABLE;
+
+
+static void die (const char *format, ...) ATTR_PRINTF(1,2);
+
+
+/* Name of this program to be printed in error messages. */
+static const char *invocation_name;
+
+/* Talk a bit about what is going on. */
+static int opt_verbose;
+
+/* Option to ignore the echo command. */
+static int opt_no_echo;
+
+/* File descriptors used to communicate with the current server. */
+static int server_send_fd = -1;
+static int server_recv_fd = -1;
+
+/* The Assuan protocol limits the line length to 1024, so we can
+ safely use a (larger) buffer. The buffer is filled using the
+ read_assuan(). */
+static char recv_line[MAX_LINELEN];
+/* Tell the status of the current line. */
+static LINETYPE recv_type;
+
+/* This is our variable storage. */
+static VARIABLE variable_list;
+
+
+static void
+die (const char *format, ...)
+{
+ va_list arg_ptr;
+
+ fflush (stdout);
+ fprintf (stderr, "%s: ", invocation_name);
+
+ va_start (arg_ptr, format);
+ vfprintf (stderr, format, arg_ptr);
+ va_end (arg_ptr);
+ putc ('\n', stderr);
+
+ exit (1);
+}
+
+#define die_0(format) (die) ("%s: " format, __func__)
+#define die_1(format, a) (die) ("%s: " format, __func__, (a))
+#define die_2(format, a, b) (die) ("%s: " format, __func__, (a),(b))
+#define die_3(format, a, b, c) (die) ("%s: " format, __func__, (a),(b),(c))
+
+static void
+err (const char *format, ...)
+{
+ va_list arg_ptr;
+
+ fflush (stdout);
+ fprintf (stderr, "%s: ", invocation_name);
+
+ va_start (arg_ptr, format);
+ vfprintf (stderr, format, arg_ptr);
+ va_end (arg_ptr);
+ putc ('\n', stderr);
+}
+
+static void *
+xmalloc (size_t n)
+{
+ void *p = malloc (n);
+ if (!p)
+ die ("out of core");
+ return p;
+}
+
+static void *
+xcalloc (size_t n, size_t m)
+{
+ void *p = calloc (n, m);
+ if (!p)
+ die ("out of core");
+ return p;
+}
+
+static char *
+xstrdup (const char *s)
+{
+ char *p = xmalloc (strlen (s)+1);
+ strcpy (p, s);
+ return p;
+}
+
+
+/* Write LENGTH bytes from BUFFER to FD. */
+static int
+writen (int fd, const char *buffer, size_t length)
+{
+ while (length)
+ {
+ int nwritten = write (fd, buffer, length);
+
+ if (nwritten < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ return -1; /* write error */
+ }
+ length -= nwritten;
+ buffer += nwritten;
+ }
+ return 0; /* okay */
+}
+
+
+
+
+/* Assuan specific stuff. */
+
+/* Read a line from FD, store it in the global recv_line, analyze the
+ type and store that in recv_type. The function terminates on a
+ communication error. Returns a pointer into the inputline to the
+ first byte of the arguments. The parsing is very strict to match
+ exaclty what we want to send. */
+static char *
+read_assuan (int fd)
+{
+ /* FIXME: For general robustness, the pending stuff needs to be
+ associated with FD. */
+ static char pending[MAX_LINELEN];
+ static size_t pending_len;
+ size_t nleft = sizeof recv_line;
+ char *buf = recv_line;
+ char *p;
+
+ while (nleft > 0)
+ {
+ int n;
+
+ if (pending_len)
+ {
+ if (pending_len >= nleft)
+ die_0 ("received line too large");
+ memcpy (buf, pending, pending_len);
+ n = pending_len;
+ pending_len = 0;
+ }
+ else
+ {
+ do
+ {
+ n = read (fd, buf, nleft);
+ }
+ while (n < 0 && errno == EINTR);
+ }
+
+ if (opt_verbose && n >= 0 )
+ {
+ int i;
+
+ printf ("%s: read \"", __func__);
+ for (i = 0; i < n; i ++)
+ putc (buf[i], stdout);
+ printf ("\"\n");
+ }
+
+ if (n < 0)
+ die_2 ("reading fd %d failed: %s", fd, strerror (errno));
+ else if (!n)
+ die_1 ("received incomplete line on fd %d", fd);
+ p = buf;
+ nleft -= n;
+ buf += n;
+
+ for (; n && *p != '\n'; n--, p++)
+ ;
+ if (n)
+ {
+ if (n>1)
+ {
+ n--;
+ memcpy (pending, p + 1, n);
+ pending_len = n;
+ }
+ *p = '\0';
+ break;
+ }
+ }
+ if (!nleft)
+ die_0 ("received line too large");
+
+ p = recv_line;
+ if (p[0] == 'O' && p[1] == 'K' && (p[2] == ' ' || !p[2]))
+ {
+ recv_type = LINE_OK;
+ p += 3;
+ }
+ else if (p[0] == 'E' && p[1] == 'R' && p[2] == 'R'
+ && (p[3] == ' ' || !p[3]))
+ {
+ recv_type = LINE_ERR;
+ p += 4;
+ }
+ else if (p[0] == 'S' && (p[1] == ' ' || !p[1]))
+ {
+ recv_type = LINE_STAT;
+ p += 2;
+ }
+ else if (p[0] == 'D' && p[1] == ' ')
+ {
+ recv_type = LINE_DATA;
+ p += 2;
+ }
+ else if (p[0] == 'E' && p[1] == 'N' && p[2] == 'D' && !p[3])
+ {
+ recv_type = LINE_END;
+ p += 3;
+ }
+ else
+ die_1 ("invalid line type (%.5s)", p);
+
+ return p;
+}
+
+/* Write LINE to the server using FD. It is expected that the line
+ contains the terminating linefeed as last character. */
+static void
+write_assuan (int fd, const char *line)
+{
+ char buffer[1026];
+ size_t n = strlen (line);
+
+ if (n > 1024)
+ die_0 ("line too long for Assuan protocol");
+ strcpy (buffer, line);
+ if (!n || buffer[n-1] != '\n')
+ buffer[n++] = '\n';
+
+ if (writen (fd, buffer, n))
+ die_3 ("sending line (\"%s\") to %d failed: %s", buffer, fd,
+ strerror (errno));
+}
+
+
+/* Start the server with path PGMNAME and connect its stdout and
+ strerr to a newly created pipes; the file descriptors are then
+ store in the gloabl variables SERVER_SEND_FD and
+ SERVER_RECV_FD. The initial handcheck is performed.*/
+static void
+start_server (const char *pgmname)
+{
+ int rp[2];
+ int wp[2];
+ pid_t pid;
+
+ if (pipe (rp) < 0)
+ die_1 ("pipe creation failed: %s", strerror (errno));
+ if (pipe (wp) < 0)
+ die_1 ("pipe creation failed: %s", strerror (errno));
+
+ fflush (stdout);
+ fflush (stderr);
+ pid = fork ();
+ if (pid < 0)
+ die_0 ("fork failed");
+
+ if (!pid)
+ {
+ const char *arg0;
+
+ arg0 = strrchr (pgmname, '/');
+ if (arg0)
+ arg0++;
+ else
+ arg0 = pgmname;
+
+ if (wp[0] != STDIN_FILENO)
+ {
+ if (dup2 (wp[0], STDIN_FILENO) == -1)
+ die_1 ("dup2 failed in child: %s", strerror (errno));
+ close (wp[0]);
+ }
+ if (rp[1] != STDOUT_FILENO)
+ {
+ if (dup2 (rp[1], STDOUT_FILENO) == -1)
+ die_1 ("dup2 failed in child: %s", strerror (errno));
+ close (rp[1]);
+ }
+ if (!opt_verbose)
+ {
+ int fd = open ("/dev/null", O_WRONLY);
+ if (fd == -1)
+ die_1 ("can't open '/dev/null': %s", strerror (errno));
+ if (dup2 (fd, STDERR_FILENO) == -1)
+ die_1 ("dup2 failed in child: %s", strerror (errno));
+ close (fd);
+ }
+
+ close (wp[1]);
+ close (rp[0]);
+ execl (pgmname, arg0, "--server", NULL);
+ die_2 ("exec failed for '%s': %s", pgmname, strerror (errno));
+ }
+ close (wp[0]);
+ close (rp[1]);
+ server_send_fd = wp[1];
+ server_recv_fd = rp[0];
+
+ read_assuan (server_recv_fd);
+ if (recv_type != LINE_OK)
+ die_0 ("no greating message");
+}
+
+
+
+
+
+/* Script intepreter. */
+
+static void
+unset_var (const char *name)
+{
+ VARIABLE var;
+
+ for (var=variable_list; var && strcmp (var->name, name); var = var->next)
+ ;
+ if (!var)
+ return;
+/* fprintf (stderr, "unsetting '%s'\n", name); */
+
+ if (var->type == VARTYPE_FD && var->value)
+ {
+ int fd;
+
+ fd = atoi (var->value);
+ if (fd != -1 && fd != 0 && fd != 1 && fd != 2)
+ close (fd);
+ }
+
+ free (var->value);
+ var->value = NULL;
+ var->type = 0;
+ var->count = 0;
+}
+
+
+static void
+set_type_var (const char *name, const char *value, VARTYPE type)
+{
+ VARIABLE var;
+
+ if (!name)
+ name = "?";
+ for (var=variable_list; var && strcmp (var->name, name); var = var->next)
+ ;
+ if (!var)
+ {
+ var = xcalloc (1, sizeof *var + strlen (name));
+ strcpy (var->name, name);
+ var->next = variable_list;
+ variable_list = var;
+ }
+ else
+ {
+ free (var->value);
+ var->value = NULL;
+ }
+
+ if (var->type == VARTYPE_FD && var->value)
+ {
+ int fd;
+
+ fd = atoi (var->value);
+ if (fd != -1 && fd != 0 && fd != 1 && fd != 2)
+ close (fd);
+ }
+
+ var->type = type;
+ var->count = 0;
+ if (var->type == VARTYPE_COUNTER)
+ {
+ /* We need some extra sapce as scratch area for get_var. */
+ var->value = xmalloc (strlen (value) + 1 + 20);
+ strcpy (var->value, value);
+ }
+ else
+ var->value = xstrdup (value);
+}
+
+static void
+set_var (const char *name, const char *value)
+{
+ set_type_var (name, value, 0);
+}
+
+
+static const char *
+get_var (const char *name)
+{
+ VARIABLE var;
+
+ for (var=variable_list; var && strcmp (var->name, name); var = var->next)
+ ;
+ if (!var)
+ return NULL;
+ if (var->type == VARTYPE_COUNTER && var->value)
+ { /* Use the scratch space allocated by set_var. */
+ char *p = var->value + strlen(var->value)+1;
+ sprintf (p, "%u", var->count);
+ return p;
+ }
+ else
+ return var->value;
+}
+
+
+/* Incremente all counter type variables with NAME in their VALUE. */
+static void
+inc_counter (const char *name)
+{
+ VARIABLE var;
+
+ if (!*name)
+ return;
+ for (var=variable_list; var; var = var->next)
+ {
+ if (var->type == VARTYPE_COUNTER
+ && var->value && !strcmp (var->value, name))
+ var->count++;
+ }
+}
+
+
+/* Expand variables in LINE and return a new allocated buffer if
+ required. The function might modify LINE if the expanded version
+ fits into it. */
+static char *
+expand_line (char *buffer)
+{
+ char *line = buffer;
+ char *p, *pend;
+ const char *value;
+ size_t valuelen, n;
+ char *result = NULL;
+
+ while (*line)
+ {
+ p = strchr (line, '$');
+ if (!p)
+ return result; /* nothing more to expand */
+
+ if (p[1] == '$') /* quoted */
+ {
+ memmove (p, p+1, strlen (p+1)+1);
+ line = p + 1;
+ continue;
+ }
+ for (pend=p+1; *pend && !spacep (pend)
+ && *pend != '$' && *pend != '/'; pend++)
+ ;
+ if (*pend)
+ {
+ int save = *pend;
+ *pend = 0;
+ value = get_var (p+1);
+ *pend = save;
+ }
+ else
+ value = get_var (p+1);
+ if (!value)
+ value = "";
+ valuelen = strlen (value);
+ if (valuelen <= pend - p)
+ {
+ memcpy (p, value, valuelen);
+ p += valuelen;
+ n = pend - p;
+ if (n)
+ memmove (p, p+n, strlen (p+n)+1);
+ line = p;
+ }
+ else
+ {
+ char *src = result? result : buffer;
+ char *dst;
+
+ dst = xmalloc (strlen (src) + valuelen + 1);
+ n = p - src;
+ memcpy (dst, src, n);
+ memcpy (dst + n, value, valuelen);
+ n += valuelen;
+ strcpy (dst + n, pend);
+ line = dst + n;
+ free (result);
+ result = dst;
+ }
+ }
+ return result;
+}
+
+
+/* Evaluate COND and return the result. */
+static int
+eval_boolean (const char *cond)
+{
+ int true = 1;
+
+ for ( ; *cond == '!'; cond++)
+ true = !true;
+ if (!*cond || (*cond == '0' && !cond[1]))
+ return !true;
+ return true;
+}
+
+
+
+
+
+static void
+cmd_let (const char *assign_to, char *arg)
+{
+ set_var (assign_to, arg);
+}
+
+
+static void
+cmd_echo (const char *assign_to, char *arg)
+{
+ (void)assign_to;
+ if (!opt_no_echo)
+ printf ("%s\n", arg);
+}
+
+static void
+cmd_send (const char *assign_to, char *arg)
+{
+ (void)assign_to;
+ if (opt_verbose)
+ fprintf (stderr, "sending '%s'\n", arg);
+ write_assuan (server_send_fd, arg);
+}
+
+static void
+handle_status_line (char *arg)
+{
+ char *p;
+
+ for (p=arg; *p && !spacep (p); p++)
+ ;
+ if (*p)
+ {
+ int save = *p;
+ *p = 0;
+ inc_counter (arg);
+ *p = save;
+ }
+ else
+ inc_counter (arg);
+}
+
+static void
+cmd_expect_ok (const char *assign_to, char *arg)
+{
+ (void)assign_to;
+ (void)arg;
+
+ if (opt_verbose)
+ fprintf (stderr, "expecting OK\n");
+ do
+ {
+ char *p = read_assuan (server_recv_fd);
+ if (opt_verbose > 1)
+ fprintf (stderr, "got line '%s'\n", recv_line);
+ if (recv_type == LINE_STAT)
+ handle_status_line (p);
+ }
+ while (recv_type != LINE_OK && recv_type != LINE_ERR);
+ if (recv_type != LINE_OK)
+ die_1 ("expected OK but got '%s'", recv_line);
+}
+
+static void
+cmd_expect_err (const char *assign_to, char *arg)
+{
+ (void)assign_to;
+ (void)arg;
+
+ if (opt_verbose)
+ fprintf (stderr, "expecting ERR\n");
+ do
+ {
+ char *p = read_assuan (server_recv_fd);
+ if (opt_verbose > 1)
+ fprintf (stderr, "got line '%s'\n", recv_line);
+ if (recv_type == LINE_STAT)
+ handle_status_line (p);
+ }
+ while (recv_type != LINE_OK && recv_type != LINE_ERR);
+ if (recv_type != LINE_ERR)
+ die_1 ("expected ERR but got '%s'", recv_line);
+}
+
+static void
+cmd_count_status (const char *assign_to, char *arg)
+{
+ char *p;
+
+ if (!*assign_to || !*arg)
+ die_0 ("syntax error: count-status requires an argument and a variable");
+
+ for (p=arg; *p && !spacep (p); p++)
+ ;
+ if (*p)
+ {
+ for (*p++ = 0; spacep (p); p++)
+ ;
+ if (*p)
+ die_0 ("cmpfiles: syntax error");
+ }
+ set_type_var (assign_to, arg, VARTYPE_COUNTER);
+}
+
+static void
+cmd_openfile (const char *assign_to, char *arg)
+{
+ int fd;
+ char numbuf[20];
+
+ do
+ fd = open (arg, O_RDONLY);
+ while (fd == -1 && errno == EINTR);
+ if (fd == -1)
+ die_2 ("error opening '%s': %s", arg, strerror (errno));
+
+ sprintf (numbuf, "%d", fd);
+ set_type_var (assign_to, numbuf, VARTYPE_FD);
+}
+
+static void
+cmd_createfile (const char *assign_to, char *arg)
+{
+ int fd;
+ char numbuf[20];
+
+ do
+ fd = open (arg, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+ while (fd == -1 && errno == EINTR);
+ if (fd == -1)
+ die_2 ("error creating '%s': %s", arg, strerror (errno));
+
+ sprintf (numbuf, "%d", fd);
+ set_type_var (assign_to, numbuf, VARTYPE_FD);
+}
+
+
+static void
+cmd_pipeserver (const char *assign_to, char *arg)
+{
+ (void)assign_to;
+
+ if (!*arg)
+ die_0 ("syntax error: servername missing");
+
+ start_server (arg);
+}
+
+
+static void
+cmd_quit_if(const char *assign_to, char *arg)
+{
+ (void)assign_to;
+
+ if (eval_boolean (arg))
+ exit (0);
+}
+
+static void
+cmd_fail_if(const char *assign_to, char *arg)
+{
+ (void)assign_to;
+
+ if (eval_boolean (arg))
+ exit (1);
+}
+
+
+static void
+cmd_cmpfiles (const char *assign_to, char *arg)
+{
+ char *p = arg;
+ char *second;
+ FILE *fp1, *fp2;
+ char buffer1[2048]; /* note: both must be of equal size. */
+ char buffer2[2048];
+ size_t nread1, nread2;
+ int rc = 0;
+
+ set_var (assign_to, "0");
+ for (p=arg; *p && !spacep (p); p++)
+ ;
+ if (!*p)
+ die_0 ("cmpfiles: syntax error");
+ for (*p++ = 0; spacep (p); p++)
+ ;
+ second = p;
+ for (; *p && !spacep (p); p++)
+ ;
+ if (*p)
+ {
+ for (*p++ = 0; spacep (p); p++)
+ ;
+ if (*p)
+ die_0 ("cmpfiles: syntax error");
+ }
+
+ fp1 = fopen (arg, "rb");
+ if (!fp1)
+ {
+ err ("can't open '%s': %s", arg, strerror (errno));
+ return;
+ }
+ fp2 = fopen (second, "rb");
+ if (!fp2)
+ {
+ err ("can't open '%s': %s", second, strerror (errno));
+ fclose (fp1);
+ return;
+ }
+ while ( (nread1 = fread (buffer1, 1, sizeof buffer1, fp1)))
+ {
+ if (ferror (fp1))
+ break;
+ nread2 = fread (buffer2, 1, sizeof buffer2, fp2);
+ if (ferror (fp2))
+ break;
+ if (nread1 != nread2 || memcmp (buffer1, buffer2, nread1))
+ {
+ rc = 1;
+ break;
+ }
+ }
+ if (feof (fp1) && feof (fp2) && !rc)
+ {
+ if (opt_verbose)
+ err ("files match");
+ set_var (assign_to, "1");
+ }
+ else if (!rc)
+ err ("cmpfiles: read error: %s", strerror (errno));
+ else
+ err ("cmpfiles: mismatch");
+ fclose (fp1);
+ fclose (fp2);
+}
+
+static void
+cmd_getenv (const char *assign_to, char *arg)
+{
+ const char *s;
+ s = *arg? getenv (arg):"";
+ set_var (assign_to, s? s:"");
+}
+
+
+
+
+/* Process the current script line LINE. */
+static int
+interpreter (char *line)
+{
+ static struct {
+ const char *name;
+ void (*fnc)(const char*, char*);
+ } cmdtbl[] = {
+ { "let" , cmd_let },
+ { "echo" , cmd_echo },
+ { "send" , cmd_send },
+ { "expect-ok" , cmd_expect_ok },
+ { "expect-err", cmd_expect_err },
+ { "count-status", cmd_count_status },
+ { "openfile" , cmd_openfile },
+ { "createfile", cmd_createfile },
+ { "pipeserver", cmd_pipeserver },
+ { "quit" , NULL },
+ { "quit-if" , cmd_quit_if },
+ { "fail-if" , cmd_fail_if },
+ { "cmpfiles" , cmd_cmpfiles },
+ { "getenv" , cmd_getenv },
+ { NULL }
+ };
+ char *p, *save_p;
+ int i, save_c;
+ char *stmt = NULL;
+ char *assign_to = NULL;
+ char *must_free = NULL;
+
+ for ( ;spacep (line); line++)
+ ;
+ if (!*line || *line == '#')
+ return 0; /* empty or comment */
+ p = expand_line (line);
+ if (p)
+ {
+ must_free = p;
+ line = p;
+ for ( ;spacep (line); line++)
+ ;
+ if (!*line || *line == '#')
+ {
+ free (must_free);
+ return 0; /* empty or comment */
+ }
+ }
+ for (p=line; *p && !spacep (p) && *p != '='; p++)
+ ;
+ if (*p == '=')
+ {
+ *p = 0;
+ assign_to = line;
+ }
+ else if (*p)
+ {
+ for (*p++ = 0; spacep (p); p++)
+ ;
+ if (*p == '=')
+ assign_to = line;
+ }
+ if (!*line)
+ die_0 ("syntax error");
+ stmt = line;
+ save_c = 0;
+ save_p = NULL;
+ if (assign_to)
+ { /* this is an assignment */
+ for (p++; spacep (p); p++)
+ ;
+ if (!*p)
+ {
+ unset_var (assign_to);
+ free (must_free);
+ return 0;
+ }
+ stmt = p;
+ for (; *p && !spacep (p); p++)
+ ;
+ if (*p)
+ {
+ save_p = p;
+ save_c = *p;
+ for (*p++ = 0; spacep (p); p++)
+ ;
+ }
+ }
+ for (i=0; cmdtbl[i].name && strcmp (stmt, cmdtbl[i].name); i++)
+ ;
+ if (!cmdtbl[i].name)
+ {
+ if (!assign_to)
+ die_1 ("invalid statement '%s'\n", stmt);
+ if (save_p)
+ *save_p = save_c;
+ set_var (assign_to, stmt);
+ free (must_free);
+ return 0;
+ }
+
+ if (cmdtbl[i].fnc)
+ cmdtbl[i].fnc (assign_to, p);
+ free (must_free);
+ return cmdtbl[i].fnc? 0:1;
+}
+
+
+
+int
+main (int argc, char **argv)
+{
+ char buffer[2048];
+ char *p, *pend;
+
+ if (!argc)
+ invocation_name = "asschk";
+ else
+ {
+ invocation_name = *argv++;
+ argc--;
+ p = strrchr (invocation_name, '/');
+ if (p)
+ invocation_name = p+1;
+ }
+
+
+ set_var ("?","1"); /* defaults to true */
+
+ for (; argc; argc--, argv++)
+ {
+ p = *argv;
+ if (*p != '-')
+ break;
+ if (!strcmp (p, "--verbose"))
+ opt_verbose++;
+ else if (!strcmp (p, "--no-echo"))
+ opt_no_echo++;
+ else if (*p == '-' && p[1] == 'D')
+ {
+ p += 2;
+ pend = strchr (p, '=');
+ if (pend)
+ {
+ int tmp = *pend;
+ *pend = 0;
+ set_var (p, pend+1);
+ *pend = tmp;
+ }
+ else
+ set_var (p, "1");
+ }
+ else if (*p == '-' && p[1] == '-' && !p[2])
+ {
+ argc--; argv++;
+ break;
+ }
+ else
+ break;
+ }
+ if (argc)
+ die ("usage: asschk [--verbose] {-D<name>[=<value>]}");
+
+
+ while (fgets (buffer, sizeof buffer, stdin))
+ {
+ p = strchr (buffer,'\n');
+ if (!p)
+ die_0 ("incomplete script line");
+ *p = 0;
+ if (interpreter (buffer))
+ break;
+ fflush (stdout);
+ }
+ return 0;
+}
diff --git a/tests/fake-pinentries/README.txt b/tests/fake-pinentries/README.txt
new file mode 100644
index 0000000..0654f56
--- /dev/null
+++ b/tests/fake-pinentries/README.txt
@@ -0,0 +1,38 @@
+Fake Pinentries for Test Suites
+===============================
+
+If you're writing a test suite, it should use one of these pinentries
+by setting the following line in $GNUPGHOME/gpg-agent.conf:
+
+ pinentry-program /path/to/fake-pinentry.ext
+
+Note that different fake-pinentry programs have been supplied here in
+different languages, with the intent of making them available to
+developers who have different languages available.
+
+They are all licensed Creative Commons Zero (CC0-1.0-Universal, see
+the COPYING.CC0 file in GnuPG's top directory), so they should be
+reusable by any project. Feel free to copy them into your own
+project's test suite.
+
+Rationale
+---------
+
+If you're implementing software that uses GnuPG, you probably want a
+test suite that exercises your code, and you may have some that
+involve secret key material locked with a passphrase. However, you
+don't want to require your developers to manually enter a passphrase
+while tests are run, and you probably also don't want to deal with
+alternate codepaths/workflows like using gpg's loopback pinentry.
+
+The solution for this is to use a fake pinentry in your test suite,
+one that simply returns a pre-selected passphrase. In this case, all
+the other code follows the same path as normal, but the user
+interaction is bypassed because the fake-pinentry is used instead.
+
+Troubleshooting
+---------------
+
+If you have any trouble with this technique, please drop a line to the
+GnuPG development mailing list <gnupg-devel@gnupg.org> or open a
+report on the GnuPG bug tracker at https://dev.gnupg.org/gnupg
diff --git a/tests/fake-pinentries/fake-pinentry.php b/tests/fake-pinentries/fake-pinentry.php
new file mode 100755
index 0000000..bc4088f
--- /dev/null
+++ b/tests/fake-pinentries/fake-pinentry.php
@@ -0,0 +1,27 @@
+#!/usr/bin/php
+<?php
+# Use this for your test suites when a PHP interpreter is available.
+#
+# The encrypted keys in your test suite that you expect to work must
+# be locked with a passphrase of "passphrase"
+#
+# Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# License: Creative Commons Zero ("Public Domain Dedication") --
+# Anyone may reuse it, modify it, redistribute it for any purpose.
+
+print("OK This is only for test suites, and should never be used in production\n");
+while (true) {
+ $line = fgets(STDIN);
+ if (False === $line)
+ break;
+ $line = strtolower(trim($line));
+ if (($line === "") || ($line[0] == '#'))
+ continue;
+ if ((0 === strncmp("getpin", $line, 6)))
+ print("D passphrase\n");
+ print("OK\n");
+ if ((0 === strncmp("bye", $line, 3)))
+ break;
+}
+?>
diff --git a/tests/fake-pinentries/fake-pinentry.pl b/tests/fake-pinentries/fake-pinentry.pl
new file mode 100755
index 0000000..8cb337d
--- /dev/null
+++ b/tests/fake-pinentries/fake-pinentry.pl
@@ -0,0 +1,27 @@
+#!/usr/bin/perl -w
+# Use this for your test suites when a perl interpreter is available.
+#
+# The encrypted keys in your test suite that you expect to work must
+# be locked with a passphrase of "passphrase"
+#
+# Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# License: Creative Commons Zero ("Public Domain Dedication") --
+# Anyone may reuse it, modify it, redistribute it for any purpose.
+
+use strict;
+use warnings;
+
+# turn off buffering
+$| = 1;
+
+print "OK This is only for test suites, and should never be used in production\n";
+while (<STDIN>) {
+ chomp;
+ next if (/^$/);
+ next if (/^#/);
+ print ("D passphrase\n") if (/^getpin/i);
+ print "OK\n";
+ exit if (/^bye/i);
+}
+1;
diff --git a/tests/fake-pinentries/fake-pinentry.py b/tests/fake-pinentries/fake-pinentry.py
new file mode 100755
index 0000000..78735c9
--- /dev/null
+++ b/tests/fake-pinentries/fake-pinentry.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+# Use this for your test suites when a python interpreter is available.
+#
+# The encrypted keys in your test suite that you expect to work must
+# be locked with a passphrase of "passphrase"
+#
+# Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# License: Creative Commons Zero ("Public Domain Dedication") --
+# Anyone may reuse it, modify it, redistribute it for any purpose.
+
+import sys, os
+
+# turn off buffering:
+sys.stdin = os.fdopen(sys.stdin.fileno(), 'r', 0)
+sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
+
+print("OK This is only for test suites, and should never be used in production")
+while True:
+ ln = sys.stdin.readline()
+ if (ln == ''):
+ break
+ ln = ln.lower()
+ if (ln.strip() == '') or (ln.startswith('#')):
+ continue
+ if (ln.startswith('getpin')):
+ sys.stdout.write('D passphrase\n')
+ sys.stdout.write('OK\n')
+ if (ln.startswith('bye')):
+ break
diff --git a/tests/fake-pinentries/fake-pinentry.sh b/tests/fake-pinentries/fake-pinentry.sh
new file mode 100755
index 0000000..44aca21
--- /dev/null
+++ b/tests/fake-pinentries/fake-pinentry.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+# Use this for your test suites when a POSIX shell is available.
+#
+# The encrypted keys in your test suite that you expect to work must
+# be locked with a passphrase of "passphrase"
+#
+# Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# License: Creative Commons Zero ("Public Domain Dedication") --
+# Anyone may reuse it, modify it, redistribute it for any purpose.
+
+echo "OK This is only for test suites, and should never be used in production"
+while read cmd rest; do
+ cmd=$(printf "%s" "$cmd" | tr 'A-Z' 'a-z')
+ if [ -z "$cmd" ]; then
+ continue;
+ fi
+ case "$cmd" in
+ \#*)
+ ;;
+ getpin)
+ echo "D passphrase"
+ echo "OK"
+ ;;
+ bye)
+ echo "OK"
+ exit 0
+ ;;
+ *)
+ echo "OK"
+ ;;
+ esac
+done
diff --git a/tests/gpgme/Makefile.am b/tests/gpgme/Makefile.am
new file mode 100644
index 0000000..60fb01d
--- /dev/null
+++ b/tests/gpgme/Makefile.am
@@ -0,0 +1,57 @@
+# Makefile.am - For tests/gpgme
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+# Process this file with automake to create Makefile.in
+
+
+# Programs required before we can run these tests.
+required_pgms = ../../g10/gpg$(EXEEXT) ../../agent/gpg-agent$(EXEEXT) \
+ ../../tools/gpg-connect-agent$(EXEEXT) \
+ ../gpgscm/gpgscm$(EXEEXT)
+
+AM_CPPFLAGS = -I$(top_srcdir)/common
+include $(top_srcdir)/am/cmacros.am
+
+AM_CFLAGS =
+
+TESTS_ENVIRONMENT = LC_ALL=C \
+ EXEEXT=$(EXEEXT) \
+ PATH="../gpgscm:$(PATH)" \
+ abs_top_srcdir=$(abs_top_srcdir) \
+ objdir=$(abs_top_builddir) \
+ GPGSCM_PATH=$(abs_top_srcdir)/tests/gpgscm
+
+# XXX: Currently, one cannot override automake's 'check' target. As a
+# workaround, we avoid defining 'TESTS', thus automake will not emit
+# the 'check' target. For extra robustness, we merely define a
+# dependency on 'xcheck', so this hack should also work even if
+# automake would emit the 'check' target, as adding dependencies to
+# targets is okay.
+check: xcheck
+
+.PHONY: xcheck
+xcheck:
+ $(TESTS_ENVIRONMENT) $(abs_top_builddir)/tests/gpgscm/gpgscm \
+ $(abs_srcdir)/run-tests.scm $(TESTFLAGS) $(TESTS)
+
+EXTRA_DIST = gpgme-defs.scm run-tests.scm setup.scm wrap.scm all-tests.scm
+
+CLEANFILES = *.log report.xml
+
+# We need to depend on a couple of programs so that the tests don't
+# start before all programs are built.
+all-local: $(required_pgms)
diff --git a/tests/gpgme/Makefile.in b/tests/gpgme/Makefile.in
new file mode 100644
index 0000000..d06bad8
--- /dev/null
+++ b/tests/gpgme/Makefile.in
@@ -0,0 +1,628 @@
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am - For tests/gpgme
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+# Process this file with automake to create Makefile.in
+
+# cmacros.am - C macro definitions
+# Copyright (C) 2004 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@HAVE_DOSISH_SYSTEM_FALSE@am__append_1 = -DGNUPG_BINDIR="\"$(bindir)\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_LIBEXECDIR="\"$(libexecdir)\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_LIBDIR="\"$(libdir)/@PACKAGE@\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_DATADIR="\"$(datadir)/@PACKAGE@\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_SYSCONFDIR="\"$(sysconfdir)/@PACKAGE@\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_LOCALSTATEDIR="\"$(localstatedir)\""
+
+
+# If a specific protect tool program has been defined, pass its name
+# to cc. Note that these macros should not be used directly but via
+# the gnupg_module_name function.
+@GNUPG_AGENT_PGM_TRUE@am__append_2 = -DGNUPG_DEFAULT_AGENT="\"@GNUPG_AGENT_PGM@\""
+@GNUPG_PINENTRY_PGM_TRUE@am__append_3 = -DGNUPG_DEFAULT_PINENTRY="\"@GNUPG_PINENTRY_PGM@\""
+@GNUPG_SCDAEMON_PGM_TRUE@am__append_4 = -DGNUPG_DEFAULT_SCDAEMON="\"@GNUPG_SCDAEMON_PGM@\""
+@GNUPG_DIRMNGR_PGM_TRUE@am__append_5 = -DGNUPG_DEFAULT_DIRMNGR="\"@GNUPG_DIRMNGR_PGM@\""
+@GNUPG_PROTECT_TOOL_PGM_TRUE@am__append_6 = -DGNUPG_DEFAULT_PROTECT_TOOL="\"@GNUPG_PROTECT_TOOL_PGM@\""
+@GNUPG_DIRMNGR_LDAP_PGM_TRUE@am__append_7 = -DGNUPG_DEFAULT_DIRMNGR_LDAP="\"@GNUPG_DIRMNGR_LDAP_PGM@\""
+subdir = tests/gpgme
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/autobuild.m4 \
+ $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/ksba.m4 \
+ $(top_srcdir)/m4/lcmessage.m4 $(top_srcdir)/m4/ldap.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libassuan.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/npth.m4 $(top_srcdir)/m4/ntbtls.m4 \
+ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \
+ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/readline.m4 \
+ $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \
+ $(top_srcdir)/m4/tar-ustar.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/am/cmacros.am \
+ $(top_srcdir)/build-aux/mkinstalldirs
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+AWK_HEX_NUMBER_OPTION = @AWK_HEX_NUMBER_OPTION@
+BUILD_FILEVERSION = @BUILD_FILEVERSION@
+BUILD_HOSTNAME = @BUILD_HOSTNAME@
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+BUILD_REVISION = @BUILD_REVISION@
+BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
+BUILD_VERSION = @BUILD_VERSION@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DL_LIBS = @DL_LIBS@
+DNSLIBS = @DNSLIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENCFS = @ENCFS@
+EXEEXT = @EXEEXT@
+FUSERMOUNT = @FUSERMOUNT@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNUPG_AGENT_PGM = @GNUPG_AGENT_PGM@
+GNUPG_DIRMNGR_LDAP_PGM = @GNUPG_DIRMNGR_LDAP_PGM@
+GNUPG_DIRMNGR_PGM = @GNUPG_DIRMNGR_PGM@
+GNUPG_PINENTRY_PGM = @GNUPG_PINENTRY_PGM@
+GNUPG_PROTECT_TOOL_PGM = @GNUPG_PROTECT_TOOL_PGM@
+GNUPG_SCDAEMON_PGM = @GNUPG_SCDAEMON_PGM@
+GPGKEYS_LDAP = @GPGKEYS_LDAP@
+GPGRT_CONFIG = @GPGRT_CONFIG@
+GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
+GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
+GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
+GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
+GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+KSBA_CFLAGS = @KSBA_CFLAGS@
+KSBA_CONFIG = @KSBA_CONFIG@
+KSBA_LIBS = @KSBA_LIBS@
+LBER_LIBS = @LBER_LIBS@
+LDAPLIBS = @LDAPLIBS@
+LDAP_CPPFLAGS = @LDAP_CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
+LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
+LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@
+LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBREADLINE = @LIBREADLINE@
+LIBS = @LIBS@
+LIBUSB_CPPFLAGS = @LIBUSB_CPPFLAGS@
+LIBUSB_LIBS = @LIBUSB_LIBS@
+LIBUTIL_LIBS = @LIBUTIL_LIBS@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NETLIBS = @NETLIBS@
+NPTH_CFLAGS = @NPTH_CFLAGS@
+NPTH_CONFIG = @NPTH_CONFIG@
+NPTH_LIBS = @NPTH_LIBS@
+NTBTLS_CFLAGS = @NTBTLS_CFLAGS@
+NTBTLS_CONFIG = @NTBTLS_CONFIG@
+NTBTLS_LIBS = @NTBTLS_LIBS@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_GT = @PACKAGE_GT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SENDMAIL = @SENDMAIL@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHRED = @SHRED@
+SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
+SQLITE3_LIBS = @SQLITE3_LIBS@
+STRIP = @STRIP@
+SYSROOT = @SYSROOT@
+SYS_SOCKET_H = @SYS_SOCKET_H@
+TAR = @TAR@
+USE_C99_CFLAGS = @USE_C99_CFLAGS@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+W32SOCKLIBS = @W32SOCKLIBS@
+WINDRES = @WINDRES@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+YAT2M = @YAT2M@
+ZLIBS = @ZLIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = $(datadir)/locale
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# Programs required before we can run these tests.
+required_pgms = ../../g10/gpg$(EXEEXT) ../../agent/gpg-agent$(EXEEXT) \
+ ../../tools/gpg-connect-agent$(EXEEXT) \
+ ../gpgscm/gpgscm$(EXEEXT)
+
+
+# NB: AM_CFLAGS may also be used by tools running on the build
+# platform to create source files.
+AM_CPPFLAGS = -I$(top_srcdir)/common -DLOCALEDIR=\"$(localedir)\" \
+ $(am__append_1) $(am__append_2) $(am__append_3) \
+ $(am__append_4) $(am__append_5) $(am__append_6) \
+ $(am__append_7)
+@HAVE_W32CE_SYSTEM_FALSE@extra_sys_libs =
+
+# Under Windows we use LockFileEx. WindowsCE provides this only on
+# the WindowsMobile 6 platform and thus we need to use the coredll6
+# import library. We also want to use a stacksize of 256k instead of
+# the 2MB which is the default with cegcc. 256k is the largest stack
+# we use with pth.
+@HAVE_W32CE_SYSTEM_TRUE@extra_sys_libs = -lcoredll6
+@HAVE_W32CE_SYSTEM_FALSE@extra_bin_ldflags =
+@HAVE_W32CE_SYSTEM_TRUE@extra_bin_ldflags = -Wl,--stack=0x40000
+resource_objs =
+
+# Convenience macros
+libcommon = ../common/libcommon.a
+libcommonpth = ../common/libcommonpth.a
+libcommontls = ../common/libcommontls.a
+libcommontlsnpth = ../common/libcommontlsnpth.a
+AM_CFLAGS =
+TESTS_ENVIRONMENT = LC_ALL=C \
+ EXEEXT=$(EXEEXT) \
+ PATH="../gpgscm:$(PATH)" \
+ abs_top_srcdir=$(abs_top_srcdir) \
+ objdir=$(abs_top_builddir) \
+ GPGSCM_PATH=$(abs_top_srcdir)/tests/gpgscm
+
+EXTRA_DIST = gpgme-defs.scm run-tests.scm setup.scm wrap.scm all-tests.scm
+CLEANFILES = *.log report.xml
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .o .rc
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/am/cmacros.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/gpgme/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu tests/gpgme/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/am/cmacros.am $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile all-local
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am all-local check check-am clean clean-generic \
+ cscopelist-am ctags-am distclean distclean-generic distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+ pdf-am ps ps-am tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+@HAVE_W32_SYSTEM_TRUE@.rc.o:
+@HAVE_W32_SYSTEM_TRUE@ $(WINDRES) $(DEFAULT_INCLUDES) $(INCLUDES) "$<" "$@"
+
+# XXX: Currently, one cannot override automake's 'check' target. As a
+# workaround, we avoid defining 'TESTS', thus automake will not emit
+# the 'check' target. For extra robustness, we merely define a
+# dependency on 'xcheck', so this hack should also work even if
+# automake would emit the 'check' target, as adding dependencies to
+# targets is okay.
+check: xcheck
+
+.PHONY: xcheck
+xcheck:
+ $(TESTS_ENVIRONMENT) $(abs_top_builddir)/tests/gpgscm/gpgscm \
+ $(abs_srcdir)/run-tests.scm $(TESTFLAGS) $(TESTS)
+
+# We need to depend on a couple of programs so that the tests don't
+# start before all programs are built.
+all-local: $(required_pgms)
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tests/gpgme/all-tests.scm b/tests/gpgme/all-tests.scm
new file mode 100644
index 0000000..f72f8af
--- /dev/null
+++ b/tests/gpgme/all-tests.scm
@@ -0,0 +1,86 @@
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(export all-tests
+ ;; Parse GPGME's makefiles to find all tests.
+
+ (load (in-srcdir "tests" "gpgme" "gpgme-defs.scm"))
+ (load (with-path "makefile.scm"))
+
+ (define (expander filename port key)
+ ;;(interactive-repl (current-environment))
+ (cond
+ ((string=? key "tests_unix")
+ (if *win32*
+ (parse-makefile port key) ;; Use win32 definition.
+ (begin
+ (parse-makefile port key) ;; Skip win32 definition.
+ (parse-makefile port key))))
+ (else
+ (parse-makefile port key))))
+
+ (define (parse filename key)
+ (parse-makefile-expand filename expander key))
+
+ (define setup-c
+ (make-environment-cache
+ (test::scm
+ #f
+ (path-join "tests" "gpgme" "setup.scm" "tests" "gpg")
+ (in-srcdir "tests" "gpgme" "setup.scm")
+ "--" "tests" "gpg")))
+ (define setup-py
+ (make-environment-cache
+ (test::scm
+ #f
+ (path-join "tests" "gpgme" "setup.scm" "lang" "python" "tests")
+ (in-srcdir "tests" "gpgme" "setup.scm")
+ "--" "lang" "python" "tests")))
+
+ (define (compiled? name)
+ (not (or (string-suffix? name ".py")
+ (string-suffix? name ".test"))))
+ (define :path car)
+ (define :key cadr)
+ (define :setup caddr)
+
+ (if (have-gpgme?)
+ (apply append
+ (map (lambda (cmpnts)
+ (define (find-test name)
+ (apply path-join
+ `(,(if (compiled? name)
+ gpgme-builddir
+ gpgme-srcdir) ,@(:path cmpnts) ,(qualify name))))
+ (let ((makefile (apply path-join `(,gpgme-srcdir ,@(:path cmpnts)
+ "Makefile.am"))))
+ (map (lambda (name)
+ (apply test::scm
+ `(,(:setup cmpnts)
+ ,(apply path-join
+ `("tests" "gpgme" ,@(:path cmpnts) ,name))
+ ,(in-srcdir "tests" "gpgme" "wrap.scm")
+ --executable
+ ,(find-test name)
+ -- ,@(:path cmpnts))))
+ (parse makefile (:key cmpnts)))))
+ `((("tests" "gpg") "c_tests" ,setup-c)
+ ,@(if (run-python-tests?)
+ `((("lang" "python" "tests") "py_tests" ,setup-py))
+ '())
+ (("lang" "qt" "tests") "TESTS" ,setup-c))))
+ '()))
diff --git a/tests/gpgme/gpgme-defs.scm b/tests/gpgme/gpgme-defs.scm
new file mode 100644
index 0000000..bc40b3c
--- /dev/null
+++ b/tests/gpgme/gpgme-defs.scm
@@ -0,0 +1,129 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+
+(define gpgme-srcdir (getenv "XTEST_GPGME_SRCDIR"))
+
+(define (in-gpgme-srcdir . names)
+ (canonical-path (apply path-join (cons gpgme-srcdir names))))
+
+(define gpgme-builddir (getenv "XTEST_GPGME_BUILDDIR"))
+
+(define (have-gpgme?)
+ (cond
+ ((string=? "" gpgme-srcdir)
+ (info
+ "SKIP: Environment variable 'XTEST_GPGME_SRCDIR' not set. Please"
+ "point it to a recent GPGME source tree to run the GPGME test suite.")
+ #f)
+ ((string=? "" gpgme-builddir)
+ (info
+ "SKIP: Environment variable 'XTEST_GPGME_BUILDDIR' not set. Please"
+ "point it to a recent GPGME build tree to run the GPGME test suite.")
+ #f)
+ (else
+ #t)))
+
+;; Make sure that GPGME picks up our gpgconf. This makes GPGME use
+;; and thus executes the tests with GnuPG components from the build
+;; tree.
+(setenv "PATH" (string-append (path-join (getenv "GNUPG_BUILDDIR") "tools")
+ (string *pathsep*) (getenv "PATH")) #t)
+
+;; The tests expect the pinentry to return the passphrase "abc".
+(setenv "PINENTRY_USER_DATA" "abc" #t)
+
+(define (create-gpgmehome . path)
+ ;; Support for various environments.
+ (define mode
+ (cond
+ ((equal? path '("lang" "python" "tests"))
+ (set! path '("tests" "gpg")) ;; Mostly uses files from tests/gpg.
+ 'python)
+ (else
+ 'gpg)))
+
+ (create-file
+ "gpg.conf"
+ "no-force-v3-sigs"
+ (string-append "agent-program " (tool 'gpg-agent) "|--debug-quick-random\n"))
+ (create-file
+ "gpg-agent.conf"
+ (string-append "pinentry-program " (tool 'pinentry))
+ "disable-scdaemon")
+
+ (start-agent)
+
+ (log "Storing private keys")
+ (for-each
+ (lambda (name)
+ (file-copy (apply in-gpgme-srcdir `(,@path ,name))
+ (path-join "private-keys-v1.d"
+ (string-append name ".key"))))
+ '("13CD0F3BDF24BE53FE192D62F18737256FF6E4FD"
+ "76F7E2B35832976B50A27A282D9B87E44577EB66"
+ "A0747D5F9425E6664F4FFBEED20FBCA79FDED2BD"
+ "13CBE3758AFE42B5E5E2AE4CED27AFA455E3F87F"
+ "7A030357C0F253A5BBCD282FFC4E521B37558F5C"))
+
+ (log "Importing public demo and test keys")
+ (for-each
+ (lambda (file)
+ (call-check `(,@GPG --yes --import ,(apply in-gpgme-srcdir
+ `(,@path ,file)))))
+ (list "pubdemo.asc" "secdemo.asc"))
+
+ (when (equal? mode 'python)
+ (log "Importing extra keys for Python tests")
+ (for-each
+ (lambda (file)
+ (call-check `(,@GPG --yes --import
+ ,(apply in-gpgme-srcdir
+ `("lang" "python" "tests" ,file)))))
+ (list "encrypt-only.asc" "sign-only.asc"))
+
+ (log "Marking key as trusted")
+ (pipe:do
+ (pipe:echo "A0FF4590BB6122EDEF6E3C542D727CC768697734:6:\n")
+ (pipe:spawn `(,(tool 'gpg) --import-ownertrust))))
+
+ (stop-agent))
+
+;; Initialize the test environment, install appropriate configuration
+;; and start the agent, with the keys from the legacy test suite.
+(define (setup-gpgme-environment . path)
+ (if (member "--unpack-tarball" *args*)
+ (begin
+ (call-check `(,(tool 'gpgtar) --extract --directory=. ,(cadr *args*)))
+ (start-agent))
+ (apply create-gpgme-gpghome path)))
+
+(define python
+ (let loop ((pythons (list "python" "python2" "python3")))
+ (if (null? pythons)
+ #f
+ (catch (loop (cdr pythons))
+ (unless (file-exists? (path-join gpgme-builddir "lang" "python"
+ (string-append (car pythons) "-gpg")))
+ (throw "next please"))
+ (path-expand (car pythons) (string-split (getenv "PATH") *pathsep*))))))
+
+(define (run-python-tests?)
+ (not (not python)))
diff --git a/tests/gpgme/run-tests.scm b/tests/gpgme/run-tests.scm
new file mode 100644
index 0000000..e81c9e9
--- /dev/null
+++ b/tests/gpgme/run-tests.scm
@@ -0,0 +1,20 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(run-tests (load-tests "tests" "gpgme"))
diff --git a/tests/gpgme/setup.scm b/tests/gpgme/setup.scm
new file mode 100644
index 0000000..d1173d8
--- /dev/null
+++ b/tests/gpgme/setup.scm
@@ -0,0 +1,35 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "gpgme" "gpgme-defs.scm"))
+
+(define tarball (flag "--create-tarball" *args*))
+(unless (and tarball (not (null? tarball)))
+ (error "Usage: setup.scm --create-tarball <file> ..."))
+
+(define components (flag "--" *args*))
+(unless (and components (not (null? components)))
+ (error "Usage: setup.scm --create-tarball " (cadr tarball)
+ " -- component [component ...]"))
+
+(with-temporary-working-directory
+ (setenv "GNUPGHOME" (getcwd) #t)
+ (apply create-gpgmehome components)
+ (stop-agent)
+ (call-check `(,(tool 'gpgtar) --create --output ,(car tarball) ".")))
diff --git a/tests/gpgme/wrap.scm b/tests/gpgme/wrap.scm
new file mode 100644
index 0000000..9a20d50
--- /dev/null
+++ b/tests/gpgme/wrap.scm
@@ -0,0 +1,66 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "gpgme" "gpgme-defs.scm"))
+
+(define executable (flag "--executable" *args*))
+(unless (and executable (not (null? executable)))
+ (error "Usage: wrap.scm --executable <file> [args...]"))
+
+(setup-gpgme-environment "tests" "gpg")
+
+(setenv "abs_builddir" (getcwd) #t)
+(setenv "top_srcdir" gpgme-srcdir #t)
+(setenv "srcdir" (path-join gpgme-srcdir "tests" "gpg") #t)
+(setenv "abs_top_srcdir" (path-join gpgme-srcdir "tests" "gpg") #t)
+
+(define (run what)
+ (if (string-suffix? (car what) ".py")
+ (begin
+ (setenv "LD_LIBRARY_PATH"
+ (if (< 0 (string-length (getenv "LD_LIBRARY_PATH")))
+ (string-append (path-join gpgme-builddir "src/.libs")
+ (string *pathsep*)
+ (getenv "LD_LIBRARY_PATH"))
+ (path-join gpgme-builddir "src/.libs"))
+ #t)
+ (if python
+ (call-with-fds
+ `(,python
+ ,(in-gpgme-srcdir "lang" "python" "tests" "run-tests.py")
+ --quiet
+ ,(string-append "--interpreters=" python)
+ --builddir ,(path-join gpgme-builddir "lang" "python" "tests")
+ ,@what)
+ STDIN_FILENO STDOUT_FILENO STDERR_FILENO)
+ 77))
+ (call-with-fds what STDIN_FILENO STDOUT_FILENO STDERR_FILENO)))
+
+(let ((name (basename (car executable))))
+ (cond
+ ((string=? (qualify "t-keylist") name)
+ ;; This test assumes that 't-import' imported a key.
+ (log "Importing extra key...")
+ (call-check `(,@GPG --yes --import ,(in-srcdir "pubkey-1.asc"))))))
+
+(if (file-exists? (car executable))
+ (begin
+ (log "Running" (car executable))
+ (exit (run executable)))
+ (skip (car executable) "is not built"))
diff --git a/tests/gpgscm/LICENSE.TinySCHEME b/tests/gpgscm/LICENSE.TinySCHEME
new file mode 100644
index 0000000..23a7e85
--- /dev/null
+++ b/tests/gpgscm/LICENSE.TinySCHEME
@@ -0,0 +1,31 @@
+ LICENSE TERMS
+
+Copyright (c) 2000, Dimitrios Souflis
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+Neither the name of Dimitrios Souflis nor the names of the
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/tests/gpgscm/Makefile.am b/tests/gpgscm/Makefile.am
new file mode 100644
index 0000000..44d7b3f
--- /dev/null
+++ b/tests/gpgscm/Makefile.am
@@ -0,0 +1,64 @@
+# TinyScheme-based test driver.
+#
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+
+EXTRA_DIST = \
+ LICENSE.TinySCHEME \
+ Manual.txt \
+ ffi.scm \
+ init.scm \
+ lib.scm \
+ makefile.scm \
+ repl.scm \
+ t-child.scm \
+ xml.scm \
+ tests.scm \
+ gnupg.scm \
+ time.scm
+
+AM_CPPFLAGS = -I$(top_srcdir)/common
+include $(top_srcdir)/am/cmacros.am
+
+AM_CFLAGS =
+
+CLEANFILES =
+
+bin_PROGRAMS = gpgscm
+noinst_PROGRAMS = t-child
+
+common_libs = ../$(libcommon)
+commonpth_libs = ../$(libcommonpth)
+
+gpgscm_CFLAGS = -imacros scheme-config.h \
+ $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(GPG_ERROR_CFLAGS)
+gpgscm_SOURCES = main.c private.h ffi.c ffi.h ffi-private.h \
+ scheme-config.h scheme.c scheme.h scheme-private.h \
+ opdefines.h small-integers.h
+gpgscm_LDADD = $(LDADD) $(common_libs) \
+ $(NETLIBS) $(LIBICONV) $(LIBREADLINE) $(LIBINTL) \
+ $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS)
+
+t_child_SOURCES = t-child.c
+
+# Make sure that all libs are build before we use them. This is
+# important for things like make -j2.
+$(PROGRAMS): $(common_libs)
+
+check-local: gpgscm$(EXEEXT) t-child$(EXEEXT)
+ EXEEXT=$(EXEEXT) GPGSCM_PATH=$(srcdir) \
+ ./gpgscm$(EXEEXT) $(srcdir)/t-child.scm
diff --git a/tests/gpgscm/Makefile.in b/tests/gpgscm/Makefile.in
new file mode 100644
index 0000000..503903a
--- /dev/null
+++ b/tests/gpgscm/Makefile.in
@@ -0,0 +1,882 @@
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# TinyScheme-based test driver.
+#
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+
+# cmacros.am - C macro definitions
+# Copyright (C) 2004 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@HAVE_DOSISH_SYSTEM_FALSE@am__append_1 = -DGNUPG_BINDIR="\"$(bindir)\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_LIBEXECDIR="\"$(libexecdir)\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_LIBDIR="\"$(libdir)/@PACKAGE@\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_DATADIR="\"$(datadir)/@PACKAGE@\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_SYSCONFDIR="\"$(sysconfdir)/@PACKAGE@\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_LOCALSTATEDIR="\"$(localstatedir)\""
+
+
+# If a specific protect tool program has been defined, pass its name
+# to cc. Note that these macros should not be used directly but via
+# the gnupg_module_name function.
+@GNUPG_AGENT_PGM_TRUE@am__append_2 = -DGNUPG_DEFAULT_AGENT="\"@GNUPG_AGENT_PGM@\""
+@GNUPG_PINENTRY_PGM_TRUE@am__append_3 = -DGNUPG_DEFAULT_PINENTRY="\"@GNUPG_PINENTRY_PGM@\""
+@GNUPG_SCDAEMON_PGM_TRUE@am__append_4 = -DGNUPG_DEFAULT_SCDAEMON="\"@GNUPG_SCDAEMON_PGM@\""
+@GNUPG_DIRMNGR_PGM_TRUE@am__append_5 = -DGNUPG_DEFAULT_DIRMNGR="\"@GNUPG_DIRMNGR_PGM@\""
+@GNUPG_PROTECT_TOOL_PGM_TRUE@am__append_6 = -DGNUPG_DEFAULT_PROTECT_TOOL="\"@GNUPG_PROTECT_TOOL_PGM@\""
+@GNUPG_DIRMNGR_LDAP_PGM_TRUE@am__append_7 = -DGNUPG_DEFAULT_DIRMNGR_LDAP="\"@GNUPG_DIRMNGR_LDAP_PGM@\""
+bin_PROGRAMS = gpgscm$(EXEEXT)
+noinst_PROGRAMS = t-child$(EXEEXT)
+subdir = tests/gpgscm
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/autobuild.m4 \
+ $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/ksba.m4 \
+ $(top_srcdir)/m4/lcmessage.m4 $(top_srcdir)/m4/ldap.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libassuan.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/npth.m4 $(top_srcdir)/m4/ntbtls.m4 \
+ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \
+ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/readline.m4 \
+ $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \
+ $(top_srcdir)/m4/tar-ustar.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
+am_gpgscm_OBJECTS = gpgscm-main.$(OBJEXT) gpgscm-ffi.$(OBJEXT) \
+ gpgscm-scheme.$(OBJEXT)
+gpgscm_OBJECTS = $(am_gpgscm_OBJECTS)
+am__DEPENDENCIES_1 =
+gpgscm_DEPENDENCIES = $(common_libs) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+gpgscm_LINK = $(CCLD) $(gpgscm_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+am_t_child_OBJECTS = t-child.$(OBJEXT)
+t_child_OBJECTS = $(am_t_child_OBJECTS)
+t_child_LDADD = $(LDADD)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/gpgscm-ffi.Po \
+ ./$(DEPDIR)/gpgscm-main.Po ./$(DEPDIR)/gpgscm-scheme.Po \
+ ./$(DEPDIR)/t-child.Po
+am__mv = mv -f
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(gpgscm_SOURCES) $(t_child_SOURCES)
+DIST_SOURCES = $(gpgscm_SOURCES) $(t_child_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/am/cmacros.am \
+ $(top_srcdir)/build-aux/depcomp \
+ $(top_srcdir)/build-aux/mkinstalldirs
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+AWK_HEX_NUMBER_OPTION = @AWK_HEX_NUMBER_OPTION@
+BUILD_FILEVERSION = @BUILD_FILEVERSION@
+BUILD_HOSTNAME = @BUILD_HOSTNAME@
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+BUILD_REVISION = @BUILD_REVISION@
+BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
+BUILD_VERSION = @BUILD_VERSION@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DL_LIBS = @DL_LIBS@
+DNSLIBS = @DNSLIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENCFS = @ENCFS@
+EXEEXT = @EXEEXT@
+FUSERMOUNT = @FUSERMOUNT@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNUPG_AGENT_PGM = @GNUPG_AGENT_PGM@
+GNUPG_DIRMNGR_LDAP_PGM = @GNUPG_DIRMNGR_LDAP_PGM@
+GNUPG_DIRMNGR_PGM = @GNUPG_DIRMNGR_PGM@
+GNUPG_PINENTRY_PGM = @GNUPG_PINENTRY_PGM@
+GNUPG_PROTECT_TOOL_PGM = @GNUPG_PROTECT_TOOL_PGM@
+GNUPG_SCDAEMON_PGM = @GNUPG_SCDAEMON_PGM@
+GPGKEYS_LDAP = @GPGKEYS_LDAP@
+GPGRT_CONFIG = @GPGRT_CONFIG@
+GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
+GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
+GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
+GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
+GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+KSBA_CFLAGS = @KSBA_CFLAGS@
+KSBA_CONFIG = @KSBA_CONFIG@
+KSBA_LIBS = @KSBA_LIBS@
+LBER_LIBS = @LBER_LIBS@
+LDAPLIBS = @LDAPLIBS@
+LDAP_CPPFLAGS = @LDAP_CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
+LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
+LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@
+LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBREADLINE = @LIBREADLINE@
+LIBS = @LIBS@
+LIBUSB_CPPFLAGS = @LIBUSB_CPPFLAGS@
+LIBUSB_LIBS = @LIBUSB_LIBS@
+LIBUTIL_LIBS = @LIBUTIL_LIBS@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NETLIBS = @NETLIBS@
+NPTH_CFLAGS = @NPTH_CFLAGS@
+NPTH_CONFIG = @NPTH_CONFIG@
+NPTH_LIBS = @NPTH_LIBS@
+NTBTLS_CFLAGS = @NTBTLS_CFLAGS@
+NTBTLS_CONFIG = @NTBTLS_CONFIG@
+NTBTLS_LIBS = @NTBTLS_LIBS@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_GT = @PACKAGE_GT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SENDMAIL = @SENDMAIL@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHRED = @SHRED@
+SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
+SQLITE3_LIBS = @SQLITE3_LIBS@
+STRIP = @STRIP@
+SYSROOT = @SYSROOT@
+SYS_SOCKET_H = @SYS_SOCKET_H@
+TAR = @TAR@
+USE_C99_CFLAGS = @USE_C99_CFLAGS@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+W32SOCKLIBS = @W32SOCKLIBS@
+WINDRES = @WINDRES@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+YAT2M = @YAT2M@
+ZLIBS = @ZLIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = $(datadir)/locale
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = \
+ LICENSE.TinySCHEME \
+ Manual.txt \
+ ffi.scm \
+ init.scm \
+ lib.scm \
+ makefile.scm \
+ repl.scm \
+ t-child.scm \
+ xml.scm \
+ tests.scm \
+ gnupg.scm \
+ time.scm
+
+
+# NB: AM_CFLAGS may also be used by tools running on the build
+# platform to create source files.
+AM_CPPFLAGS = -I$(top_srcdir)/common -DLOCALEDIR=\"$(localedir)\" \
+ $(am__append_1) $(am__append_2) $(am__append_3) \
+ $(am__append_4) $(am__append_5) $(am__append_6) \
+ $(am__append_7)
+@HAVE_W32CE_SYSTEM_FALSE@extra_sys_libs =
+
+# Under Windows we use LockFileEx. WindowsCE provides this only on
+# the WindowsMobile 6 platform and thus we need to use the coredll6
+# import library. We also want to use a stacksize of 256k instead of
+# the 2MB which is the default with cegcc. 256k is the largest stack
+# we use with pth.
+@HAVE_W32CE_SYSTEM_TRUE@extra_sys_libs = -lcoredll6
+@HAVE_W32CE_SYSTEM_FALSE@extra_bin_ldflags =
+@HAVE_W32CE_SYSTEM_TRUE@extra_bin_ldflags = -Wl,--stack=0x40000
+resource_objs =
+
+# Convenience macros
+libcommon = ../common/libcommon.a
+libcommonpth = ../common/libcommonpth.a
+libcommontls = ../common/libcommontls.a
+libcommontlsnpth = ../common/libcommontlsnpth.a
+AM_CFLAGS =
+CLEANFILES =
+common_libs = ../$(libcommon)
+commonpth_libs = ../$(libcommonpth)
+gpgscm_CFLAGS = -imacros scheme-config.h \
+ $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(GPG_ERROR_CFLAGS)
+
+gpgscm_SOURCES = main.c private.h ffi.c ffi.h ffi-private.h \
+ scheme-config.h scheme.c scheme.h scheme-private.h \
+ opdefines.h small-integers.h
+
+gpgscm_LDADD = $(LDADD) $(common_libs) \
+ $(NETLIBS) $(LIBICONV) $(LIBREADLINE) $(LIBINTL) \
+ $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS)
+
+t_child_SOURCES = t-child.c
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj .rc
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/am/cmacros.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/gpgscm/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu tests/gpgscm/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/am/cmacros.am $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+
+gpgscm$(EXEEXT): $(gpgscm_OBJECTS) $(gpgscm_DEPENDENCIES) $(EXTRA_gpgscm_DEPENDENCIES)
+ @rm -f gpgscm$(EXEEXT)
+ $(AM_V_CCLD)$(gpgscm_LINK) $(gpgscm_OBJECTS) $(gpgscm_LDADD) $(LIBS)
+
+t-child$(EXEEXT): $(t_child_OBJECTS) $(t_child_DEPENDENCIES) $(EXTRA_t_child_DEPENDENCIES)
+ @rm -f t-child$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(t_child_OBJECTS) $(t_child_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgscm-ffi.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgscm-main.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgscm-scheme.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-child.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+gpgscm-main.o: main.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgscm_CFLAGS) $(CFLAGS) -MT gpgscm-main.o -MD -MP -MF $(DEPDIR)/gpgscm-main.Tpo -c -o gpgscm-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gpgscm-main.Tpo $(DEPDIR)/gpgscm-main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main.c' object='gpgscm-main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgscm_CFLAGS) $(CFLAGS) -c -o gpgscm-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
+
+gpgscm-main.obj: main.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgscm_CFLAGS) $(CFLAGS) -MT gpgscm-main.obj -MD -MP -MF $(DEPDIR)/gpgscm-main.Tpo -c -o gpgscm-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gpgscm-main.Tpo $(DEPDIR)/gpgscm-main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main.c' object='gpgscm-main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgscm_CFLAGS) $(CFLAGS) -c -o gpgscm-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi`
+
+gpgscm-ffi.o: ffi.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgscm_CFLAGS) $(CFLAGS) -MT gpgscm-ffi.o -MD -MP -MF $(DEPDIR)/gpgscm-ffi.Tpo -c -o gpgscm-ffi.o `test -f 'ffi.c' || echo '$(srcdir)/'`ffi.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gpgscm-ffi.Tpo $(DEPDIR)/gpgscm-ffi.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ffi.c' object='gpgscm-ffi.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgscm_CFLAGS) $(CFLAGS) -c -o gpgscm-ffi.o `test -f 'ffi.c' || echo '$(srcdir)/'`ffi.c
+
+gpgscm-ffi.obj: ffi.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgscm_CFLAGS) $(CFLAGS) -MT gpgscm-ffi.obj -MD -MP -MF $(DEPDIR)/gpgscm-ffi.Tpo -c -o gpgscm-ffi.obj `if test -f 'ffi.c'; then $(CYGPATH_W) 'ffi.c'; else $(CYGPATH_W) '$(srcdir)/ffi.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gpgscm-ffi.Tpo $(DEPDIR)/gpgscm-ffi.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ffi.c' object='gpgscm-ffi.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgscm_CFLAGS) $(CFLAGS) -c -o gpgscm-ffi.obj `if test -f 'ffi.c'; then $(CYGPATH_W) 'ffi.c'; else $(CYGPATH_W) '$(srcdir)/ffi.c'; fi`
+
+gpgscm-scheme.o: scheme.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgscm_CFLAGS) $(CFLAGS) -MT gpgscm-scheme.o -MD -MP -MF $(DEPDIR)/gpgscm-scheme.Tpo -c -o gpgscm-scheme.o `test -f 'scheme.c' || echo '$(srcdir)/'`scheme.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gpgscm-scheme.Tpo $(DEPDIR)/gpgscm-scheme.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='scheme.c' object='gpgscm-scheme.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgscm_CFLAGS) $(CFLAGS) -c -o gpgscm-scheme.o `test -f 'scheme.c' || echo '$(srcdir)/'`scheme.c
+
+gpgscm-scheme.obj: scheme.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgscm_CFLAGS) $(CFLAGS) -MT gpgscm-scheme.obj -MD -MP -MF $(DEPDIR)/gpgscm-scheme.Tpo -c -o gpgscm-scheme.obj `if test -f 'scheme.c'; then $(CYGPATH_W) 'scheme.c'; else $(CYGPATH_W) '$(srcdir)/scheme.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gpgscm-scheme.Tpo $(DEPDIR)/gpgscm-scheme.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='scheme.c' object='gpgscm-scheme.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gpgscm_CFLAGS) $(CFLAGS) -c -o gpgscm-scheme.obj `if test -f 'scheme.c'; then $(CYGPATH_W) 'scheme.c'; else $(CYGPATH_W) '$(srcdir)/scheme.c'; fi`
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-local
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/gpgscm-ffi.Po
+ -rm -f ./$(DEPDIR)/gpgscm-main.Po
+ -rm -f ./$(DEPDIR)/gpgscm-scheme.Po
+ -rm -f ./$(DEPDIR)/t-child.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/gpgscm-ffi.Po
+ -rm -f ./$(DEPDIR)/gpgscm-main.Po
+ -rm -f ./$(DEPDIR)/gpgscm-scheme.Po
+ -rm -f ./$(DEPDIR)/t-child.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am \
+ check-local clean clean-binPROGRAMS clean-generic \
+ clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-binPROGRAMS install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS
+
+.PRECIOUS: Makefile
+
+
+@HAVE_W32_SYSTEM_TRUE@.rc.o:
+@HAVE_W32_SYSTEM_TRUE@ $(WINDRES) $(DEFAULT_INCLUDES) $(INCLUDES) "$<" "$@"
+
+# Make sure that all libs are build before we use them. This is
+# important for things like make -j2.
+$(PROGRAMS): $(common_libs)
+
+check-local: gpgscm$(EXEEXT) t-child$(EXEEXT)
+ EXEEXT=$(EXEEXT) GPGSCM_PATH=$(srcdir) \
+ ./gpgscm$(EXEEXT) $(srcdir)/t-child.scm
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tests/gpgscm/Manual.txt b/tests/gpgscm/Manual.txt
new file mode 100644
index 0000000..b146926
--- /dev/null
+++ b/tests/gpgscm/Manual.txt
@@ -0,0 +1,444 @@
+
+
+ TinySCHEME Version 1.41
+
+ "Safe if used as prescribed"
+ -- Philip K. Dick, "Ubik"
+
+This software is open source, covered by a BSD-style license.
+Please read accompanying file COPYING.
+-------------------------------------------------------------------------------
+
+ This Scheme interpreter is based on MiniSCHEME version 0.85k4
+ (see miniscm.tar.gz in the Scheme Repository)
+ Original credits in file MiniSCHEMETribute.txt.
+
+ D. Souflis (dsouflis@acm.org)
+
+-------------------------------------------------------------------------------
+ What is TinyScheme?
+ -------------------
+
+ TinyScheme is a lightweight Scheme interpreter that implements as large
+ a subset of R5RS as was possible without getting very large and
+ complicated. It is meant to be used as an embedded scripting interpreter
+ for other programs. As such, it does not offer IDEs or extensive toolkits
+ although it does sport a small top-level loop, included conditionally.
+ A lot of functionality in TinyScheme is included conditionally, to allow
+ developers freedom in balancing features and footprint.
+
+ As an embedded interpreter, it allows multiple interpreter states to
+ coexist in the same program, without any interference between them.
+ Programmatically, foreign functions in C can be added and values
+ can be defined in the Scheme environment. Being a quite small program,
+ it is easy to comprehend, get to grips with, and use.
+
+ Known bugs
+ ----------
+
+ TinyScheme is known to misbehave when memory is exhausted.
+
+
+ Things that keep missing, or that need fixing
+ ---------------------------------------------
+
+ There are no hygienic macros. No rational or
+ complex numbers. No unwind-protect and call-with-values.
+
+ Maybe (a subset of) SLIB will work with TinySCHEME...
+
+ Decent debugging facilities are missing. Only tracing is supported
+ natively.
+
+
+ Scheme Reference
+ ----------------
+
+ If something seems to be missing, please refer to the code and
+ "init.scm", since some are library functions. Refer to the MiniSCHEME
+ readme as a last resort.
+
+ Environments
+ (interaction-environment)
+ See R5RS. In TinySCHEME, immutable list of association lists.
+
+ (current-environment)
+ The environment in effect at the time of the call. An example of its
+ use and its utility can be found in the sample code that implements
+ packages in "init.scm":
+
+ (macro (package form)
+ `(apply (lambda ()
+ ,@(cdr form)
+ (current-environment))))
+
+ The environment containing the (local) definitions inside the closure
+ is returned as an immutable value.
+
+ (defined? <symbol>) (defined? <symbol> <environment>)
+ Checks whether the given symbol is defined in the current (or given)
+ environment.
+
+ Symbols
+ (gensym)
+ Returns a new interned symbol each time. Will probably move to the
+ library when string->symbol is implemented.
+
+ Directives
+ (gc)
+ Performs garbage collection immediately.
+
+ (gc-verbose) (gc-verbose <bool>)
+ The argument (defaulting to #t) controls whether GC produces
+ visible outcome.
+
+ (quit) (quit <num>)
+ Stops the interpreter and sets the 'retcode' internal field (defaults
+ to 0). When standalone, 'retcode' is returned as exit code to the OS.
+
+ (tracing <num>)
+ 1, turns on tracing. 0 turns it off. (Only when USE_TRACING is 1).
+
+ Mathematical functions
+ Since rationals and complexes are absent, the respective functions
+ are also missing.
+ Supported: exp, log, sin, cos, tan, asin, acos, atan, floor, ceiling,
+ trunc, round and also sqrt and expt when USE_MATH=1.
+ Number-theoretical quotient, remainder and modulo, gcd, lcm.
+ Library: exact?, inexact?, odd?, even?, zero?, positive?, negative?,
+ exact->inexact. inexact->exact is a core function.
+
+ Type predicates
+ boolean?,eof-object?,symbol?,number?,string?,integer?,real?,list?,null?,
+ char?,port?,input-port?,output-port?,procedure?,pair?,environment?',
+ vector?. Also closure?, macro?.
+
+ Types
+ Types supported:
+
+ Numbers (integers and reals)
+ Symbols
+ Pairs
+ Strings
+ Characters
+ Ports
+ Eof object
+ Environments
+ Vectors
+
+ Literals
+ String literals can contain escaped quotes \" as usual, but also
+ \n, \r, \t, \xDD (hex representations) and \DDD (octal representations).
+ Note also that it is possible to include literal newlines in string
+ literals, e.g.
+
+ (define s "String with newline here
+ and here
+ that can function like a HERE-string")
+
+ Character literals contain #\space and #\newline and are supplemented
+ with #\return and #\tab, with obvious meanings. Hex character
+ representations are allowed (e.g. #\x20 is #\space).
+ When USE_ASCII_NAMES is defined, various control characters can be
+ referred to by their ASCII name.
+ 0 #\nul 17 #\dc1
+ 1 #\soh 18 #\dc2
+ 2 #\stx 19 #\dc3
+ 3 #\etx 20 #\dc4
+ 4 #\eot 21 #\nak
+ 5 #\enq 22 #\syn
+ 6 #\ack 23 #\etv
+ 7 #\bel 24 #\can
+ 8 #\bs 25 #\em
+ 9 #\ht 26 #\sub
+ 10 #\lf 27 #\esc
+ 11 #\vt 28 #\fs
+ 12 #\ff 29 #\gs
+ 13 #\cr 30 #\rs
+ 14 #\so 31 #\us
+ 15 #\si
+ 16 #\dle 127 #\del
+
+ Numeric literals support #x #o #b and #d. Flonums are currently read only
+ in decimal notation. Full grammar will be supported soon.
+
+ Quote, quasiquote etc.
+ As usual.
+
+ Immutable values
+ Immutable pairs cannot be modified by set-car! and set-cdr!.
+ Immutable strings cannot be modified via string-set!
+
+ I/O
+ As per R5RS, plus String Ports (see below).
+ current-input-port, current-output-port,
+ close-input-port, close-output-port, input-port?, output-port?,
+ open-input-file, open-output-file.
+ read, write, display, newline, write-char, read-char, peek-char.
+ char-ready? returns #t only for string ports, because there is no
+ portable way in stdio to determine if a character is available.
+ Also open-input-output-file, set-input-port, set-output-port (not R5RS)
+ Library: call-with-input-file, call-with-output-file,
+ with-input-from-file, with-output-from-file and
+ with-input-output-from-to-files, close-port and input-output-port?
+ (not R5RS).
+ String Ports: open-input-string, open-output-string, get-output-string,
+ open-input-output-string. Strings can be used with I/O routines.
+
+ Vectors
+ make-vector, vector, vector-length, vector-ref, vector-set!, list->vector,
+ vector-fill!, vector->list, vector-equal? (auxiliary function, not R5RS)
+
+ Strings
+ string, make-string, list->string, string-length, string-ref, string-set!,
+ substring, string->list, string-fill!, string-append, string-copy.
+ string=?, string<?, string>?, string>?, string<=?, string>=?.
+ (No string-ci*? yet). string->number, number->string. Also atom->string,
+ string->atom (not R5RS).
+
+ Symbols
+ symbol->string, string->symbol
+
+ Characters
+ integer->char, char->integer.
+ char=?, char<?, char>?, char<=?, char>=?.
+ (No char-ci*?)
+
+ Pairs & Lists
+ cons, car, cdr, list, length, map, for-each, foldr, list-tail,
+ list-ref, last-pair, reverse, append.
+ Also member, memq, memv, based on generic-member, assoc, assq, assv
+ based on generic-assoc.
+
+ Streams
+ head, tail, cons-stream
+
+ Control features
+ Apart from procedure?, also macro? and closure?
+ map, for-each, force, delay, call-with-current-continuation (or call/cc),
+ eval, apply. 'Forcing' a value that is not a promise produces the value.
+ There is no call-with-values, values, nor dynamic-wind. Dynamic-wind in
+ the presence of continuations would require support from the abstract
+ machine itself.
+
+ Property lists
+ TinyScheme inherited from MiniScheme property lists for symbols.
+ put, get.
+
+ Dynamically-loaded extensions
+ (load-extension <filename without extension>)
+ Loads a DLL declaring foreign procedures. On Unix/Linux, one can make use
+ of the ld.so.conf file or the LD_RUN_PATH system variable in order to place
+ the library in a directory other than the current one. Please refer to the
+ appropriate 'man' page.
+
+ Esoteric procedures
+ (oblist)
+ Returns the oblist, an immutable list of all the symbols.
+
+ (macro-expand <form>)
+ Returns the expanded form of the macro call denoted by the argument
+
+ (define-with-return (<procname> <args>...) <body>)
+ Like plain 'define', but makes the continuation available as 'return'
+ inside the procedure. Handy for imperative programs.
+
+ (new-segment <num>)
+ Allocates more memory segments.
+
+ defined?
+ See "Environments"
+
+ (get-closure-code <closure>)
+ Gets the code as scheme data.
+
+ (make-closure <code> <environment>)
+ Makes a new closure in the given environment.
+
+ Obsolete procedures
+ (print-width <object>)
+
+ Programmer's Reference
+ ----------------------
+
+ The interpreter state is initialized with "scheme_init".
+ Custom memory allocation routines can be installed with an alternate
+ initialization function: "scheme_init_custom_alloc".
+ Files can be loaded with "scheme_load_file". Strings containing Scheme
+ code can be loaded with "scheme_load_string". It is a good idea to
+ "scheme_load" init.scm before anything else.
+
+ External data for keeping external state (of use to foreign functions)
+ can be installed with "scheme_set_external_data".
+ Foreign functions are installed with "assign_foreign". Additional
+ definitions can be added to the interpreter state, with "scheme_define"
+ (this is the way HTTP header data and HTML form data are passed to the
+ Scheme script in the Altera SQL Server). If you wish to define the
+ foreign function in a specific environment (to enhance modularity),
+ use "assign_foreign_env".
+
+ The procedure "scheme_apply0" has been added with persistent scripts in
+ mind. Persistent scripts are loaded once, and every time they are needed
+ to produce HTTP output, appropriate data are passed through global
+ definitions and function "main" is called to do the job. One could
+ add easily "scheme_apply1" etc.
+
+ The interpreter state should be deinitialized with "scheme_deinit".
+
+ DLLs containing foreign functions should define a function named
+ init_<base-name>. E.g. foo.dll should define init_foo, and bar.so
+ should define init_bar. This function should assign_foreign any foreign
+ function contained in the DLL.
+
+ The first dynamically loaded extension available for TinyScheme is
+ a regular expression library. Although it's by no means an
+ established standard, this library is supposed to be installed in
+ a directory mirroring its name under the TinyScheme location.
+
+
+ Foreign Functions
+ -----------------
+
+ The user can add foreign functions in C. For example, a function
+ that squares its argument:
+
+ pointer square(scheme *sc, pointer args) {
+ if(args!=sc->NIL) {
+ if(sc->isnumber(sc->pair_car(args))) {
+ double v=sc->rvalue(sc->pair_car(args));
+ return sc->mk_real(sc,v*v);
+ }
+ }
+ return sc->NIL;
+ }
+
+ Foreign functions are now defined as closures:
+
+ sc->interface->scheme_define(
+ sc,
+ sc->global_env,
+ sc->interface->mk_symbol(sc,"square"),
+ sc->interface->mk_foreign_func(sc, square));
+
+
+ Foreign functions can use the external data in the "scheme" struct
+ to implement any kind of external state.
+
+ External data are set with the following function:
+ void scheme_set_external_data(scheme *sc, void *p);
+
+ As of v.1.17, the canonical way for a foreign function in a DLL to
+ manipulate Scheme data is using the function pointers in sc->interface.
+
+ Standalone
+ ----------
+
+ Usage: tinyscheme -?
+ or: tinyscheme [<file1> <file2> ...]
+ followed by
+ -1 <file> [<arg1> <arg2> ...]
+ -c <Scheme commands> [<arg1> <arg2> ...]
+ assuming that the executable is named tinyscheme.
+
+ Use - in the place of a filename to denote stdin.
+ The -1 flag is meant for #! usage in shell scripts. If you specify
+ #! /somewhere/tinyscheme -1
+ then tinyscheme will be called to process the file. For example, the
+ following script echoes the Scheme list of its arguments.
+
+ #! /somewhere/tinyscheme -1
+ (display *args*)
+
+ The -c flag permits execution of arbitrary Scheme code.
+
+
+ Error Handling
+ --------------
+
+ Errors are recovered from without damage. The user can install his
+ own handler for system errors, by defining *error-hook*. Defining
+ to '() gives the default behavior, which is equivalent to "error".
+ USE_ERROR_HOOK must be defined.
+
+ A simple exception handling mechanism can be found in "init.scm".
+ A new syntactic form is introduced:
+
+ (catch <expr returned exceptionally>
+ <expr1> <expr2> ... <exprN>)
+
+ "Catch" establishes a scope spanning multiple call-frames
+ until another "catch" is encountered.
+
+ Exceptions are thrown with:
+
+ (throw "message")
+
+ If used outside a (catch ...), reverts to (error "message").
+
+ Example of use:
+
+ (define (foo x) (write x) (newline) (/ x 0))
+
+ (catch (begin (display "Error!\n") 0)
+ (write "Before foo ... ")
+ (foo 5)
+ (write "After foo"))
+
+ The exception mechanism can be used even by system errors, by
+
+ (define *error-hook* throw)
+
+ which makes use of the error hook described above.
+
+ If necessary, the user can devise his own exception mechanism with
+ tagged exceptions etc.
+
+
+ Reader extensions
+ -----------------
+
+ When encountering an unknown character after '#', the user-specified
+ procedure *sharp-hook* (if any), is called to read the expression.
+ This can be used to extend the reader to handle user-defined constants
+ or whatever. It should be a procedure without arguments, reading from
+ the current input port (which will be the load-port).
+
+
+ Colon Qualifiers - Packages
+ ---------------------------
+
+ When USE_COLON_HOOK=1:
+ The lexer now recognizes the construction <qualifier>::<symbol> and
+ transforms it in the following manner (T is the transformation function):
+
+ T(<qualifier>::<symbol>) = (*colon-hook* 'T(<symbol>) <qualifier>)
+
+ where <qualifier> is a symbol not containing any double-colons.
+
+ As the definition is recursive, qualifiers can be nested.
+ The user can define his own *colon-hook*, to handle qualified names.
+ By default, "init.scm" defines *colon-hook* as EVAL. Consequently,
+ the qualifier must denote a Scheme environment, such as one returned
+ by (interaction-environment). "Init.scm" defines a new syntantic form,
+ PACKAGE, as a simple example. It is used like this:
+
+ (define toto
+ (package
+ (define foo 1)
+ (define bar +)))
+
+ foo ==> Error, "foo" undefined
+ (eval 'foo) ==> Error, "foo" undefined
+ (eval 'foo toto) ==> 1
+ toto::foo ==> 1
+ ((eval 'bar toto) 2 (eval 'foo toto)) ==> 3
+ (toto::bar 2 toto::foo) ==> 3
+ (eval (bar 2 foo) toto) ==> 3
+
+ If the user installs another package infrastructure, he must define
+ a new 'package' procedure or macro to retain compatibility with supplied
+ code.
+
+ Note: Older versions used ':' as a qualifier. Unfortunately, the use
+ of ':' as a pseudo-qualifier in existing code (i.e. SLIB) essentially
+ precludes its use as a real qualifier.
diff --git a/tests/gpgscm/ffi-private.h b/tests/gpgscm/ffi-private.h
new file mode 100644
index 0000000..037da56
--- /dev/null
+++ b/tests/gpgscm/ffi-private.h
@@ -0,0 +1,148 @@
+/* FFI interface for TinySCHEME.
+ *
+ * Copyright (C) 2016 g10 code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef GPGSCM_FFI_PRIVATE_H
+#define GPGSCM_FFI_PRIVATE_H
+
+#include <gpg-error.h>
+#include "scheme.h"
+#include "scheme-private.h"
+
+#define FFI_PROLOG() \
+ unsigned int ffi_arg_index GPGRT_ATTR_UNUSED = 1; \
+ int err GPGRT_ATTR_UNUSED = 0 \
+
+int ffi_bool_value (scheme *sc, pointer p);
+
+#define CONVERSION_number(SC, X) (SC)->vptr->ivalue (X)
+#define CONVERSION_string(SC, X) (SC)->vptr->string_value (X)
+#define CONVERSION_character(SC, X) (SC)->vptr->charvalue (X)
+#define CONVERSION_list(SC, X) (X)
+#define CONVERSION_bool(SC, X) ffi_bool_value ((SC), (X))
+#define CONVERSION_path(SC, X) (((SC)->vptr->is_string (X) \
+ ? (SC)->vptr->string_value \
+ : (SC)->vptr->symname) (X))
+
+#define IS_A_number(SC, X) (SC)->vptr->is_number (X)
+#define IS_A_string(SC, X) (SC)->vptr->is_string (X)
+#define IS_A_character(SC, X) (SC)->vptr->is_character (X)
+#define IS_A_list(SC, X) (SC)->vptr->is_list ((SC), X)
+#define IS_A_bool(SC, X) ((X) == (SC)->F || (X) == (SC)->T)
+#define IS_A_path(SC, X) ((SC)->vptr->is_string (X) \
+ || (SC)->vptr->is_symbol (X))
+
+#define FFI_ARG_OR_RETURN(SC, CTYPE, TARGET, WANT, ARGS) \
+ do { \
+ if ((ARGS) == (SC)->NIL) \
+ return (SC)->vptr->mk_string ((SC), \
+ "too few arguments: want " \
+ #TARGET "("#WANT"/"#CTYPE")\n"); \
+ if (! IS_A_##WANT ((SC), pair_car (ARGS))) { \
+ char ffi_error_message[256]; \
+ snprintf (ffi_error_message, sizeof ffi_error_message, \
+ "argument %d must be: " #WANT "\n", ffi_arg_index); \
+ return (SC)->vptr->mk_string ((SC), ffi_error_message); \
+ } \
+ TARGET = CONVERSION_##WANT (SC, pair_car (ARGS)); \
+ ARGS = pair_cdr (ARGS); \
+ ffi_arg_index += 1; \
+ } while (0)
+
+#define FFI_ARGS_DONE_OR_RETURN(SC, ARGS) \
+ do { \
+ if ((ARGS) != (SC)->NIL) \
+ return (SC)->vptr->mk_string ((SC), "too many arguments"); \
+ } while (0)
+
+#define FFI_RETURN_ERR(SC, ERR) \
+ return _cons ((SC), mk_integer ((SC), (ERR)), (SC)->NIL, 1)
+
+#define FFI_RETURN(SC) FFI_RETURN_ERR (SC, err)
+
+#define FFI_RETURN_POINTER(SC, X) \
+ return _cons ((SC), mk_integer ((SC), err), \
+ _cons ((SC), (X), (SC)->NIL, 1), 1)
+#define FFI_RETURN_INT(SC, X) \
+ FFI_RETURN_POINTER ((SC), mk_integer ((SC), (X)))
+#define FFI_RETURN_STRING(SC, X) \
+ FFI_RETURN_POINTER ((SC), mk_string ((SC), (X)))
+
+char *ffi_schemify_name (const char *s, int macro);
+
+void ffi_scheme_eval (scheme *sc, const char *format, ...)
+ GPGRT_ATTR_PRINTF (2, 3);
+pointer ffi_sprintf (scheme *sc, const char *format, ...)
+ GPGRT_ATTR_PRINTF (2, 3);
+
+#define ffi_define_function_name(SC, NAME, F) \
+ do { \
+ char *_fname = ffi_schemify_name ("__" #F, 0); \
+ scheme_define ((SC), \
+ (SC)->global_env, \
+ mk_symbol ((SC), _fname), \
+ mk_foreign_func ((SC), (do_##F))); \
+ ffi_scheme_eval ((SC), \
+ "(define (%s . a) (ffi-apply \"%s\" %s a))", \
+ (NAME), (NAME), _fname); \
+ free (_fname); \
+ } while (0)
+
+#define ffi_define_function(SC, F) \
+ do { \
+ char *_name = ffi_schemify_name (#F, 0); \
+ ffi_define_function_name ((SC), _name, F); \
+ free (_name); \
+ } while (0)
+
+#define ffi_define_constant(SC, C) \
+ do { \
+ char *_name = ffi_schemify_name (#C, 1); \
+ scheme_define ((SC), \
+ (SC)->global_env, \
+ mk_symbol ((SC), _name), \
+ mk_integer ((SC), (C))); \
+ free (_name); \
+ } while (0)
+
+#define ffi_define(SC, SYM, EXP) \
+ scheme_define ((SC), (SC)->global_env, mk_symbol ((SC), (SYM)), EXP)
+
+#define ffi_define_variable_pointer(SC, C, P) \
+ do { \
+ char *_name = ffi_schemify_name (#C, 0); \
+ scheme_define ((SC), \
+ (SC)->global_env, \
+ mk_symbol ((SC), _name), \
+ (P)); \
+ free (_name); \
+ } while (0)
+
+#define ffi_define_variable_integer(SC, C) \
+ ffi_define_variable_pointer ((SC), C, (SC)->vptr->mk_integer ((SC), C))
+
+#define ffi_define_variable_string(SC, C) \
+ ffi_define_variable_pointer ((SC), C, (SC)->vptr->mk_string ((SC), C ?: ""))
+
+gpg_error_t ffi_list2argv (scheme *sc, pointer list,
+ char ***argv, size_t *len);
+gpg_error_t ffi_list2intv (scheme *sc, pointer list,
+ int **intv, size_t *len);
+
+#endif /* GPGSCM_FFI_PRIVATE_H */
diff --git a/tests/gpgscm/ffi.c b/tests/gpgscm/ffi.c
new file mode 100644
index 0000000..dde5b52
--- /dev/null
+++ b/tests/gpgscm/ffi.c
@@ -0,0 +1,1470 @@
+/* FFI interface for TinySCHEME.
+ *
+ * Copyright (C) 2016 g10 code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gpg-error.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#if HAVE_LIBREADLINE
+#define GNUPG_LIBREADLINE_H_INCLUDED
+#include <readline/readline.h>
+#include <readline/history.h>
+#endif
+
+#include "../../common/util.h"
+#include "../../common/exechelp.h"
+#include "../../common/sysutils.h"
+
+#include "private.h"
+#include "ffi.h"
+#include "ffi-private.h"
+
+/* For use in nice error messages. */
+static const char *
+ordinal_suffix (int n)
+{
+ switch (n)
+ {
+ case 1: return "st";
+ case 2: return "nd";
+ case 3: return "rd";
+ default: return "th";
+ }
+ assert (! "reached");
+}
+
+
+
+int
+ffi_bool_value (scheme *sc, pointer p)
+{
+ return ! (p == sc->F);
+}
+
+
+
+static pointer
+do_logand (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ unsigned int v, acc = ~0;
+ while (args != sc->NIL)
+ {
+ FFI_ARG_OR_RETURN (sc, unsigned int, v, number, args);
+ acc &= v;
+ }
+ FFI_RETURN_INT (sc, acc);
+}
+
+static pointer
+do_logior (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ unsigned int v, acc = 0;
+ while (args != sc->NIL)
+ {
+ FFI_ARG_OR_RETURN (sc, unsigned int, v, number, args);
+ acc |= v;
+ }
+ FFI_RETURN_INT (sc, acc);
+}
+
+static pointer
+do_logxor (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ unsigned int v, acc = 0;
+ while (args != sc->NIL)
+ {
+ FFI_ARG_OR_RETURN (sc, unsigned int, v, number, args);
+ acc ^= v;
+ }
+ FFI_RETURN_INT (sc, acc);
+}
+
+static pointer
+do_lognot (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ unsigned int v;
+ FFI_ARG_OR_RETURN (sc, unsigned int, v, number, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ FFI_RETURN_INT (sc, ~v);
+}
+
+/* User interface. */
+
+static pointer
+do_flush_stdio (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ fflush (stdout);
+ fflush (stderr);
+ FFI_RETURN (sc);
+}
+
+
+int use_libreadline;
+
+/* Read a string, and return a pointer to it. Returns NULL on EOF. */
+char *
+rl_gets (const char *prompt)
+{
+ static char *line = NULL;
+ char *p;
+ xfree (line);
+
+#if HAVE_LIBREADLINE
+ {
+ line = readline (prompt);
+ if (line && *line)
+ add_history (line);
+ }
+#else
+ {
+ size_t max_size = 0xff;
+ printf ("%s", prompt);
+ fflush (stdout);
+ line = xtrymalloc (max_size);
+ if (line != NULL)
+ fgets (line, max_size, stdin);
+ }
+#endif
+
+ /* Strip trailing whitespace. */
+ if (line && strlen (line) > 0)
+ for (p = &line[strlen (line) - 1]; isspace (*p); p--)
+ *p = 0;
+
+ return line;
+}
+
+static pointer
+do_prompt (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ const char *prompt;
+ const char *line;
+ FFI_ARG_OR_RETURN (sc, const char *, prompt, string, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ line = rl_gets (prompt);
+ if (! line)
+ FFI_RETURN_POINTER (sc, sc->EOF_OBJ);
+
+ FFI_RETURN_STRING (sc, line);
+}
+
+static pointer
+do_sleep (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ unsigned int seconds;
+ FFI_ARG_OR_RETURN (sc, unsigned int, seconds, number, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ sleep (seconds);
+ FFI_RETURN (sc);
+}
+
+static pointer
+do_usleep (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ useconds_t microseconds;
+ FFI_ARG_OR_RETURN (sc, useconds_t, microseconds, number, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ usleep (microseconds);
+ FFI_RETURN (sc);
+}
+
+static pointer
+do_chdir (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ char *name;
+ FFI_ARG_OR_RETURN (sc, char *, name, path, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ if (chdir (name))
+ FFI_RETURN_ERR (sc, errno);
+ FFI_RETURN (sc);
+}
+
+static pointer
+do_strerror (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ int error;
+ FFI_ARG_OR_RETURN (sc, int, error, number, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ FFI_RETURN_STRING (sc, gpg_strerror (error));
+}
+
+static pointer
+do_getenv (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ char *name;
+ char *value;
+ FFI_ARG_OR_RETURN (sc, char *, name, string, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ value = getenv (name);
+ FFI_RETURN_STRING (sc, value ? value : "");
+}
+
+static pointer
+do_setenv (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ char *name;
+ char *value;
+ int overwrite;
+ FFI_ARG_OR_RETURN (sc, char *, name, string, args);
+ FFI_ARG_OR_RETURN (sc, char *, value, string, args);
+ FFI_ARG_OR_RETURN (sc, int, overwrite, bool, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ if (gnupg_setenv (name, value, overwrite))
+ FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
+ FFI_RETURN (sc);
+}
+
+static pointer
+do_exit (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ int retcode;
+ FFI_ARG_OR_RETURN (sc, int, retcode, number, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ exit (retcode);
+}
+
+/* XXX: use gnupgs variant b/c mode as string */
+static pointer
+do_open (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ int fd;
+ char *pathname;
+ int flags;
+ mode_t mode = 0;
+ FFI_ARG_OR_RETURN (sc, char *, pathname, path, args);
+ FFI_ARG_OR_RETURN (sc, int, flags, number, args);
+ if (args != sc->NIL)
+ FFI_ARG_OR_RETURN (sc, mode_t, mode, number, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+
+ fd = open (pathname, flags, mode);
+ if (fd == -1)
+ FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
+ FFI_RETURN_INT (sc, fd);
+}
+
+static pointer
+do_fdopen (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ FILE *stream;
+ int fd;
+ char *mode;
+ int kind;
+ FFI_ARG_OR_RETURN (sc, int, fd, number, args);
+ FFI_ARG_OR_RETURN (sc, char *, mode, string, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+
+ stream = fdopen (fd, mode);
+ if (stream == NULL)
+ FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
+
+ if (setvbuf (stream, NULL, _IONBF, 0) != 0)
+ FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
+
+ kind = 0;
+ if (strchr (mode, 'r'))
+ kind |= port_input;
+ if (strchr (mode, 'w'))
+ kind |= port_output;
+
+ FFI_RETURN_POINTER (sc, sc->vptr->mk_port_from_file (sc, stream, kind));
+}
+
+static pointer
+do_close (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ int fd;
+ FFI_ARG_OR_RETURN (sc, int, fd, number, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ FFI_RETURN_ERR (sc, close (fd) == 0 ? 0 : gpg_error_from_syserror ());
+}
+
+static pointer
+do_seek (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ int fd;
+ off_t offset;
+ int whence;
+ FFI_ARG_OR_RETURN (sc, int, fd, number, args);
+ FFI_ARG_OR_RETURN (sc, off_t, offset, number, args);
+ FFI_ARG_OR_RETURN (sc, int, whence, number, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ FFI_RETURN_ERR (sc, lseek (fd, offset, whence) == (off_t) -1
+ ? gpg_error_from_syserror () : 0);
+}
+
+static pointer
+do_get_temp_path (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+#ifdef HAVE_W32_SYSTEM
+ char buffer[MAX_PATH+1];
+#endif
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+
+#ifdef HAVE_W32_SYSTEM
+ if (GetTempPath (MAX_PATH+1, buffer) == 0)
+ FFI_RETURN_STRING (sc, "/temp");
+ FFI_RETURN_STRING (sc, buffer);
+#else
+ FFI_RETURN_STRING (sc, "/tmp");
+#endif
+}
+
+static pointer
+do_mkdtemp (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ char *template;
+#ifdef PATH_MAX
+ char buffer[PATH_MAX];
+#else
+ char buffer[1024];
+#endif
+ char *name;
+ FFI_ARG_OR_RETURN (sc, char *, template, string, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+
+ if (strlen (template) > sizeof buffer - 1)
+ FFI_RETURN_ERR (sc, EINVAL);
+ strncpy (buffer, template, sizeof buffer);
+
+ name = gnupg_mkdtemp (buffer);
+ if (name == NULL)
+ FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
+ FFI_RETURN_STRING (sc, name);
+}
+
+static pointer
+do_unlink (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ char *name;
+ FFI_ARG_OR_RETURN (sc, char *, name, string, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ if (unlink (name) == -1)
+ FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
+ FFI_RETURN (sc);
+}
+
+static gpg_error_t
+unlink_recursively (const char *name)
+{
+ gpg_error_t err = 0;
+ struct stat st;
+
+ if (stat (name, &st) == -1)
+ return gpg_error_from_syserror ();
+
+ if (S_ISDIR (st.st_mode))
+ {
+ DIR *dir;
+ struct dirent *dent;
+
+ dir = opendir (name);
+ if (dir == NULL)
+ return gpg_error_from_syserror ();
+
+ while ((dent = readdir (dir)))
+ {
+ char *child;
+
+ if (strcmp (dent->d_name, ".") == 0
+ || strcmp (dent->d_name, "..") == 0)
+ continue;
+
+ child = xtryasprintf ("%s/%s", name, dent->d_name);
+ if (child == NULL)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+
+ err = unlink_recursively (child);
+ xfree (child);
+ if (err == gpg_error_from_errno (ENOENT))
+ err = 0;
+ if (err)
+ goto leave;
+ }
+
+ leave:
+ closedir (dir);
+ if (! err)
+ rmdir (name);
+ return err;
+ }
+ else
+ if (unlink (name) == -1)
+ return gpg_error_from_syserror ();
+ return 0;
+}
+
+static pointer
+do_unlink_recursively (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ char *name;
+ FFI_ARG_OR_RETURN (sc, char *, name, string, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ err = unlink_recursively (name);
+ FFI_RETURN (sc);
+}
+
+static pointer
+do_rename (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ char *old;
+ char *new;
+ FFI_ARG_OR_RETURN (sc, char *, old, string, args);
+ FFI_ARG_OR_RETURN (sc, char *, new, string, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ if (rename (old, new) == -1)
+ FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
+ FFI_RETURN (sc);
+}
+
+static pointer
+do_getcwd (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ pointer result;
+ char *cwd;
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ cwd = gnupg_getcwd ();
+ if (cwd == NULL)
+ FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
+ result = sc->vptr->mk_string (sc, cwd);
+ xfree (cwd);
+ FFI_RETURN_POINTER (sc, result);
+}
+
+static pointer
+do_mkdir (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ char *name;
+ char *mode;
+ FFI_ARG_OR_RETURN (sc, char *, name, string, args);
+ FFI_ARG_OR_RETURN (sc, char *, mode, string, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ if (gnupg_mkdir (name, mode) == -1)
+ FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
+ FFI_RETURN (sc);
+}
+
+static pointer
+do_rmdir (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ char *name;
+ FFI_ARG_OR_RETURN (sc, char *, name, string, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ if (rmdir (name) == -1)
+ FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
+ FFI_RETURN (sc);
+}
+
+static pointer
+do_get_isotime (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ gnupg_isotime_t timebuf;
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ gnupg_get_isotime (timebuf);
+ FFI_RETURN_STRING (sc, timebuf);
+}
+
+static pointer
+do_get_time (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ FFI_RETURN_INT (sc, gnupg_get_time ());
+}
+
+static pointer
+do_getpid (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ FFI_RETURN_INT (sc, getpid ());
+}
+
+static pointer
+do_srandom (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ int seed;
+ FFI_ARG_OR_RETURN (sc, int, seed, number, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ srand (seed);
+ FFI_RETURN (sc);
+}
+
+static int
+random_scaled (int scale)
+{
+ int v;
+#ifdef HAVE_RAND
+ v = rand ();
+#else
+ v = random ();
+#endif
+
+#ifndef RAND_MAX /* for SunOS */
+#define RAND_MAX 32767
+#endif
+
+ return ((int) (1 + (int) ((float) scale * v / (RAND_MAX + 1.0))) - 1);
+}
+
+static pointer
+do_random (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ int scale;
+ FFI_ARG_OR_RETURN (sc, int, scale, number, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ FFI_RETURN_INT (sc, random_scaled (scale));
+}
+
+static pointer
+do_make_random_string (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ int size;
+ pointer chunk;
+ char *p;
+ FFI_ARG_OR_RETURN (sc, int, size, number, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ if (size < 0)
+ return ffi_sprintf (sc, "size must be positive");
+
+ chunk = sc->vptr->mk_counted_string (sc, NULL, size);
+ if (sc->no_memory)
+ FFI_RETURN_ERR (sc, ENOMEM);
+
+ for (p = sc->vptr->string_value (chunk); size; p++, size--)
+ *p = (char) random_scaled (256);
+ FFI_RETURN_POINTER (sc, chunk);
+}
+
+
+
+/* estream functions. */
+
+struct es_object_box
+{
+ estream_t stream;
+ int closed;
+};
+
+static void
+es_object_finalize (scheme *sc, void *data)
+{
+ struct es_object_box *box = data;
+ (void) sc;
+
+ if (! box->closed)
+ es_fclose (box->stream);
+ xfree (box);
+}
+
+static void
+es_object_to_string (scheme *sc, char *out, size_t size, void *data)
+{
+ struct es_object_box *box = data;
+ (void) sc;
+
+ snprintf (out, size, "#estream %p", box->stream);
+}
+
+static struct foreign_object_vtable es_object_vtable =
+ {
+ es_object_finalize,
+ es_object_to_string,
+ };
+
+static pointer
+es_wrap (scheme *sc, estream_t stream)
+{
+ struct es_object_box *box = xmalloc (sizeof *box);
+ if (box == NULL)
+ return sc->NIL;
+
+ box->stream = stream;
+ box->closed = 0;
+ return sc->vptr->mk_foreign_object (sc, &es_object_vtable, box);
+}
+
+static struct es_object_box *
+es_unwrap (scheme *sc, pointer object)
+{
+ (void) sc;
+
+ if (! is_foreign_object (object))
+ return NULL;
+
+ if (sc->vptr->get_foreign_object_vtable (object) != &es_object_vtable)
+ return NULL;
+
+ return sc->vptr->get_foreign_object_data (object);
+}
+
+#define CONVERSION_estream(SC, X) es_unwrap (SC, X)
+#define IS_A_estream(SC, X) es_unwrap (SC, X)
+
+static pointer
+do_es_fclose (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ struct es_object_box *box;
+ FFI_ARG_OR_RETURN (sc, struct es_object_box *, box, estream, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ err = es_fclose (box->stream);
+ if (! err)
+ box->closed = 1;
+ FFI_RETURN (sc);
+}
+
+static pointer
+do_es_read (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ struct es_object_box *box;
+ size_t bytes_to_read;
+
+ pointer result;
+ void *buffer;
+ size_t bytes_read;
+
+ FFI_ARG_OR_RETURN (sc, struct es_object_box *, box, estream, args);
+ FFI_ARG_OR_RETURN (sc, size_t, bytes_to_read, number, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+
+ buffer = xtrymalloc (bytes_to_read);
+ if (buffer == NULL)
+ FFI_RETURN_ERR (sc, ENOMEM);
+
+ err = es_read (box->stream, buffer, bytes_to_read, &bytes_read);
+ if (err)
+ FFI_RETURN_ERR (sc, err);
+
+ result = sc->vptr->mk_counted_string (sc, buffer, bytes_read);
+ xfree (buffer);
+ FFI_RETURN_POINTER (sc, result);
+}
+
+static pointer
+do_es_feof (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ struct es_object_box *box;
+ FFI_ARG_OR_RETURN (sc, struct es_object_box *, box, estream, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+
+ FFI_RETURN_POINTER (sc, es_feof (box->stream) ? sc->T : sc->F);
+}
+
+static pointer
+do_es_write (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ struct es_object_box *box;
+ const char *buffer;
+ size_t bytes_to_write, bytes_written;
+
+ FFI_ARG_OR_RETURN (sc, struct es_object_box *, box, estream, args);
+ /* XXX how to get the length of the string buffer? scheme strings
+ may contain \0. */
+ FFI_ARG_OR_RETURN (sc, const char *, buffer, string, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+
+ bytes_to_write = strlen (buffer);
+ while (bytes_to_write > 0)
+ {
+ err = es_write (box->stream, buffer, bytes_to_write, &bytes_written);
+ if (err)
+ break;
+ bytes_to_write -= bytes_written;
+ buffer += bytes_written;
+ }
+
+ FFI_RETURN (sc);
+}
+
+
+
+/* Process handling. */
+
+static pointer
+do_spawn_process (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ pointer arguments;
+ char **argv;
+ size_t len;
+ unsigned int flags;
+
+ estream_t infp;
+ estream_t outfp;
+ estream_t errfp;
+ pid_t pid;
+
+ FFI_ARG_OR_RETURN (sc, pointer, arguments, list, args);
+ FFI_ARG_OR_RETURN (sc, unsigned int, flags, number, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+
+ err = ffi_list2argv (sc, arguments, &argv, &len);
+ if (err == gpg_error (GPG_ERR_INV_VALUE))
+ return ffi_sprintf (sc, "%luth element of first argument is "
+ "neither string nor symbol",
+ (unsigned long) len);
+ if (err)
+ FFI_RETURN_ERR (sc, err);
+
+ if (verbose > 1)
+ {
+ char **p;
+ fprintf (stderr, "Executing:");
+ for (p = argv; *p; p++)
+ fprintf (stderr, " '%s'", *p);
+ fprintf (stderr, "\n");
+ }
+
+ err = gnupg_spawn_process (argv[0], (const char **) &argv[1],
+ NULL,
+ NULL,
+ flags,
+ &infp, &outfp, &errfp, &pid);
+ xfree (argv);
+#define IMC(A, B) \
+ _cons (sc, sc->vptr->mk_integer (sc, (unsigned long) (A)), (B), 1)
+#define IMS(A, B) \
+ _cons (sc, es_wrap (sc, (A)), (B), 1)
+ FFI_RETURN_POINTER (sc, IMS (infp,
+ IMS (outfp,
+ IMS (errfp,
+ IMC (pid, sc->NIL)))));
+#undef IMS
+#undef IMC
+}
+
+static pointer
+do_spawn_process_fd (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ pointer arguments;
+ char **argv;
+ size_t len;
+ int infd, outfd, errfd;
+
+ pid_t pid;
+
+ FFI_ARG_OR_RETURN (sc, pointer, arguments, list, args);
+ FFI_ARG_OR_RETURN (sc, int, infd, number, args);
+ FFI_ARG_OR_RETURN (sc, int, outfd, number, args);
+ FFI_ARG_OR_RETURN (sc, int, errfd, number, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+
+ err = ffi_list2argv (sc, arguments, &argv, &len);
+ if (err == gpg_error (GPG_ERR_INV_VALUE))
+ return ffi_sprintf (sc, "%luth element of first argument is "
+ "neither string nor symbol",
+ (unsigned long) len);
+ if (err)
+ FFI_RETURN_ERR (sc, err);
+
+ if (verbose > 1)
+ {
+ char **p;
+ fprintf (stderr, "Executing:");
+ for (p = argv; *p; p++)
+ fprintf (stderr, " '%s'", *p);
+ fprintf (stderr, "\n");
+ }
+
+ err = gnupg_spawn_process_fd (argv[0], (const char **) &argv[1],
+ infd, outfd, errfd, &pid);
+ xfree (argv);
+ FFI_RETURN_INT (sc, pid);
+}
+
+static pointer
+do_wait_process (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ const char *name;
+ pid_t pid;
+ int hang;
+
+ int retcode;
+
+ FFI_ARG_OR_RETURN (sc, const char *, name, string, args);
+ FFI_ARG_OR_RETURN (sc, pid_t, pid, number, args);
+ FFI_ARG_OR_RETURN (sc, int, hang, bool, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ err = gnupg_wait_process (name, pid, hang, &retcode);
+ if (err == GPG_ERR_GENERAL)
+ err = 0; /* Let the return code speak for itself. */
+
+ FFI_RETURN_INT (sc, retcode);
+}
+
+
+static pointer
+do_wait_processes (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ pointer list_names;
+ char **names;
+ pointer list_pids;
+ size_t i, count;
+ pid_t *pids;
+ int hang;
+ int *retcodes;
+ pointer retcodes_list = sc->NIL;
+
+ FFI_ARG_OR_RETURN (sc, pointer, list_names, list, args);
+ FFI_ARG_OR_RETURN (sc, pointer, list_pids, list, args);
+ FFI_ARG_OR_RETURN (sc, int, hang, bool, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+
+ if (sc->vptr->list_length (sc, list_names)
+ != sc->vptr->list_length (sc, list_pids))
+ return
+ sc->vptr->mk_string (sc, "length of first two arguments must match");
+
+ err = ffi_list2argv (sc, list_names, &names, &count);
+ if (err == gpg_error (GPG_ERR_INV_VALUE))
+ return ffi_sprintf (sc, "%lu%s element of first argument is "
+ "neither string nor symbol",
+ (unsigned long) count,
+ ordinal_suffix ((int) count));
+ if (err)
+ FFI_RETURN_ERR (sc, err);
+
+ err = ffi_list2intv (sc, list_pids, (int **) &pids, &count);
+ if (err == gpg_error (GPG_ERR_INV_VALUE))
+ return ffi_sprintf (sc, "%lu%s element of second argument is "
+ "not a number",
+ (unsigned long) count,
+ ordinal_suffix ((int) count));
+ if (err)
+ FFI_RETURN_ERR (sc, err);
+
+ retcodes = xtrycalloc (sizeof *retcodes, count);
+ if (retcodes == NULL)
+ {
+ xfree (names);
+ xfree (pids);
+ FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
+ }
+
+ err = gnupg_wait_processes ((const char **) names, pids, count, hang,
+ retcodes);
+ if (err == GPG_ERR_GENERAL)
+ err = 0; /* Let the return codes speak. */
+ if (err == GPG_ERR_TIMEOUT)
+ err = 0; /* We may have got some results. */
+
+ for (i = 0; i < count; i++)
+ retcodes_list =
+ (sc->vptr->cons) (sc,
+ sc->vptr->mk_integer (sc,
+ (long) retcodes[count-1-i]),
+ retcodes_list);
+
+ xfree (names);
+ xfree (pids);
+ xfree (retcodes);
+ FFI_RETURN_POINTER (sc, retcodes_list);
+}
+
+
+static pointer
+do_pipe (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ int filedes[2];
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ err = gnupg_create_pipe (filedes);
+#define IMC(A, B) \
+ _cons (sc, sc->vptr->mk_integer (sc, (unsigned long) (A)), (B), 1)
+ FFI_RETURN_POINTER (sc, IMC (filedes[0],
+ IMC (filedes[1], sc->NIL)));
+#undef IMC
+}
+
+static pointer
+do_inbound_pipe (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ int filedes[2];
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ err = gnupg_create_inbound_pipe (filedes, NULL, 0);
+#define IMC(A, B) \
+ _cons (sc, sc->vptr->mk_integer (sc, (unsigned long) (A)), (B), 1)
+ FFI_RETURN_POINTER (sc, IMC (filedes[0],
+ IMC (filedes[1], sc->NIL)));
+#undef IMC
+}
+
+static pointer
+do_outbound_pipe (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ int filedes[2];
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ err = gnupg_create_outbound_pipe (filedes, NULL, 0);
+#define IMC(A, B) \
+ _cons (sc, sc->vptr->mk_integer (sc, (unsigned long) (A)), (B), 1)
+ FFI_RETURN_POINTER (sc, IMC (filedes[0],
+ IMC (filedes[1], sc->NIL)));
+#undef IMC
+}
+
+
+
+/* Test helper functions. */
+static pointer
+do_file_equal (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ pointer result = sc->F;
+ char *a_name, *b_name;
+ int binary;
+ const char *mode;
+ FILE *a_stream = NULL, *b_stream = NULL;
+ struct stat a_stat, b_stat;
+#define BUFFER_SIZE 1024
+ char a_buf[BUFFER_SIZE], b_buf[BUFFER_SIZE];
+#undef BUFFER_SIZE
+ size_t chunk;
+
+ FFI_ARG_OR_RETURN (sc, char *, a_name, string, args);
+ FFI_ARG_OR_RETURN (sc, char *, b_name, string, args);
+ FFI_ARG_OR_RETURN (sc, int, binary, bool, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+
+ mode = binary ? "rb" : "r";
+ a_stream = fopen (a_name, mode);
+ if (a_stream == NULL)
+ goto errout;
+
+ b_stream = fopen (b_name, mode);
+ if (b_stream == NULL)
+ goto errout;
+
+ if (fstat (fileno (a_stream), &a_stat) < 0)
+ goto errout;
+
+ if (fstat (fileno (b_stream), &b_stat) < 0)
+ goto errout;
+
+ if (binary && a_stat.st_size != b_stat.st_size)
+ {
+ if (verbose)
+ fprintf (stderr, "Files %s and %s differ in size %lu != %lu\n",
+ a_name, b_name, (unsigned long) a_stat.st_size,
+ (unsigned long) b_stat.st_size);
+
+ goto out;
+ }
+
+ while (! feof (a_stream))
+ {
+ chunk = sizeof a_buf;
+
+ chunk = fread (a_buf, 1, chunk, a_stream);
+ if (chunk == 0 && ferror (a_stream))
+ goto errout; /* some error */
+
+ if (fread (b_buf, 1, chunk, b_stream) < chunk)
+ {
+ if (feof (b_stream))
+ goto out; /* short read */
+ goto errout; /* some error */
+ }
+
+ if (chunk > 0 && memcmp (a_buf, b_buf, chunk) != 0)
+ goto out;
+ }
+
+ fread (b_buf, 1, 1, b_stream);
+ if (! feof (b_stream))
+ goto out; /* b is longer */
+
+ /* They match. */
+ result = sc->T;
+
+ out:
+ if (a_stream)
+ fclose (a_stream);
+ if (b_stream)
+ fclose (b_stream);
+ FFI_RETURN_POINTER (sc, result);
+ errout:
+ err = gpg_error_from_syserror ();
+ goto out;
+}
+
+static pointer
+do_splice (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ int source;
+ char buffer[1024];
+ ssize_t bytes_read;
+ pointer sinks, sink;
+ FFI_ARG_OR_RETURN (sc, int, source, number, args);
+ sinks = args;
+ if (sinks == sc->NIL)
+ return ffi_sprintf (sc, "need at least one sink");
+ for (sink = sinks; sink != sc->NIL; sink = pair_cdr (sink), ffi_arg_index++)
+ if (! sc->vptr->is_number (pair_car (sink)))
+ return ffi_sprintf (sc, "%d%s argument is not a number",
+ ffi_arg_index, ordinal_suffix (ffi_arg_index));
+
+ while (1)
+ {
+ bytes_read = read (source, buffer, sizeof buffer);
+ if (bytes_read == 0)
+ break;
+ if (bytes_read < 0)
+ FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
+
+ for (sink = sinks; sink != sc->NIL; sink = pair_cdr (sink))
+ {
+ int fd = sc->vptr->ivalue (pair_car (sink));
+ char *p = buffer;
+ ssize_t left = bytes_read;
+
+ while (left)
+ {
+ ssize_t written = write (fd, p, left);
+ if (written < 0)
+ FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
+ assert (written <= left);
+ left -= written;
+ p += written;
+ }
+ }
+ }
+ FFI_RETURN (sc);
+}
+
+static pointer
+do_string_index (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ char *haystack;
+ char needle;
+ ssize_t offset = 0;
+ char *position;
+ FFI_ARG_OR_RETURN (sc, char *, haystack, string, args);
+ FFI_ARG_OR_RETURN (sc, char, needle, character, args);
+ if (args != sc->NIL)
+ {
+ FFI_ARG_OR_RETURN (sc, ssize_t, offset, number, args);
+ if (offset < 0)
+ return ffi_sprintf (sc, "offset must be positive");
+ if (offset > strlen (haystack))
+ return ffi_sprintf (sc, "offset exceeds haystack");
+ }
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+
+ position = strchr (haystack+offset, needle);
+ if (position)
+ FFI_RETURN_INT (sc, position - haystack);
+ else
+ FFI_RETURN_POINTER (sc, sc->F);
+}
+
+static pointer
+do_string_rindex (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ char *haystack;
+ char needle;
+ ssize_t offset = 0;
+ char *position;
+ FFI_ARG_OR_RETURN (sc, char *, haystack, string, args);
+ FFI_ARG_OR_RETURN (sc, char, needle, character, args);
+ if (args != sc->NIL)
+ {
+ FFI_ARG_OR_RETURN (sc, ssize_t, offset, number, args);
+ if (offset < 0)
+ return ffi_sprintf (sc, "offset must be positive");
+ if (offset > strlen (haystack))
+ return ffi_sprintf (sc, "offset exceeds haystack");
+ }
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+
+ position = strrchr (haystack+offset, needle);
+ if (position)
+ FFI_RETURN_INT (sc, position - haystack);
+ else
+ FFI_RETURN_POINTER (sc, sc->F);
+}
+
+static pointer
+do_string_contains (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ char *haystack;
+ char *needle;
+ FFI_ARG_OR_RETURN (sc, char *, haystack, string, args);
+ FFI_ARG_OR_RETURN (sc, char *, needle, string, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ FFI_RETURN_POINTER (sc, strstr (haystack, needle) ? sc->T : sc->F);
+}
+
+
+
+static pointer
+do_get_verbose (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+ FFI_RETURN_INT (sc, verbose);
+}
+
+static pointer
+do_set_verbose (scheme *sc, pointer args)
+{
+ FFI_PROLOG ();
+ int new_verbosity, old;
+ FFI_ARG_OR_RETURN (sc, int, new_verbosity, number, args);
+ FFI_ARGS_DONE_OR_RETURN (sc, args);
+
+ old = verbose;
+ verbose = new_verbosity;
+
+ FFI_RETURN_INT (sc, old);
+}
+
+
+gpg_error_t
+ffi_list2argv (scheme *sc, pointer list, char ***argv, size_t *len)
+{
+ int i;
+
+ *len = sc->vptr->list_length (sc, list);
+ *argv = xtrycalloc (*len + 1, sizeof **argv);
+ if (*argv == NULL)
+ return gpg_error_from_syserror ();
+
+ for (i = 0; sc->vptr->is_pair (list); list = sc->vptr->pair_cdr (list))
+ {
+ if (sc->vptr->is_string (sc->vptr->pair_car (list)))
+ (*argv)[i++] = sc->vptr->string_value (sc->vptr->pair_car (list));
+ else if (sc->vptr->is_symbol (sc->vptr->pair_car (list)))
+ (*argv)[i++] = sc->vptr->symname (sc->vptr->pair_car (list));
+ else
+ {
+ xfree (*argv);
+ *argv = NULL;
+ *len = i;
+ return gpg_error (GPG_ERR_INV_VALUE);
+ }
+ }
+ (*argv)[i] = NULL;
+ return 0;
+}
+
+gpg_error_t
+ffi_list2intv (scheme *sc, pointer list, int **intv, size_t *len)
+{
+ int i;
+
+ *len = sc->vptr->list_length (sc, list);
+ *intv = xtrycalloc (*len, sizeof **intv);
+ if (*intv == NULL)
+ return gpg_error_from_syserror ();
+
+ for (i = 0; sc->vptr->is_pair (list); list = sc->vptr->pair_cdr (list))
+ {
+ if (sc->vptr->is_number (sc->vptr->pair_car (list)))
+ (*intv)[i++] = sc->vptr->ivalue (sc->vptr->pair_car (list));
+ else
+ {
+ xfree (*intv);
+ *intv = NULL;
+ *len = i;
+ return gpg_error (GPG_ERR_INV_VALUE);
+ }
+ }
+
+ return 0;
+}
+
+
+char *
+ffi_schemify_name (const char *s, int macro)
+{
+ /* Fixme: We should use xtrystrdup and return NULL. However, this
+ * requires a lot more changes. Simply returning S as done
+ * originally is not an option. */
+ char *n = xstrdup (s), *p;
+ /* if (n == NULL) */
+ /* return s; */
+
+ for (p = n; *p; p++)
+ {
+ *p = (char) tolower (*p);
+ /* We convert _ to - in identifiers. We allow, however, for
+ function names to start with a leading _. The functions in
+ this namespace are not yet finalized and might change or
+ vanish without warning. Use them with care. */
+ if (! macro
+ && p != n
+ && *p == '_')
+ *p = '-';
+ }
+ return n;
+}
+
+pointer
+ffi_sprintf (scheme *sc, const char *format, ...)
+{
+ pointer result;
+ va_list listp;
+ char *expression;
+ int size, written;
+
+ va_start (listp, format);
+ size = vsnprintf (NULL, 0, format, listp);
+ va_end (listp);
+
+ expression = xtrymalloc (size + 1);
+ if (expression == NULL)
+ return NULL;
+
+ va_start (listp, format);
+ written = vsnprintf (expression, size + 1, format, listp);
+ va_end (listp);
+
+ assert (size == written);
+
+ result = sc->vptr->mk_string (sc, expression);
+ xfree (expression);
+ return result;
+}
+
+void
+ffi_scheme_eval (scheme *sc, const char *format, ...)
+{
+ va_list listp;
+ char *expression;
+ int size, written;
+
+ va_start (listp, format);
+ size = vsnprintf (NULL, 0, format, listp);
+ va_end (listp);
+
+ expression = xtrymalloc (size + 1);
+ if (expression == NULL)
+ return;
+
+ va_start (listp, format);
+ written = vsnprintf (expression, size + 1, format, listp);
+ va_end (listp);
+
+ assert (size == written);
+
+ sc->vptr->load_string (sc, expression);
+ xfree (expression);
+}
+
+gpg_error_t
+ffi_init (scheme *sc, const char *argv0, const char *scriptname,
+ int argc, const char **argv)
+{
+ int i;
+ pointer args = sc->NIL;
+
+ /* bitwise arithmetic */
+ ffi_define_function (sc, logand);
+ ffi_define_function (sc, logior);
+ ffi_define_function (sc, logxor);
+ ffi_define_function (sc, lognot);
+
+ /* libc. */
+ ffi_define_constant (sc, O_RDONLY);
+ ffi_define_constant (sc, O_WRONLY);
+ ffi_define_constant (sc, O_RDWR);
+ ffi_define_constant (sc, O_CREAT);
+ ffi_define_constant (sc, O_APPEND);
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+#ifndef O_TEXT
+# define O_TEXT 0
+#endif
+ ffi_define_constant (sc, O_BINARY);
+ ffi_define_constant (sc, O_TEXT);
+ ffi_define_constant (sc, STDIN_FILENO);
+ ffi_define_constant (sc, STDOUT_FILENO);
+ ffi_define_constant (sc, STDERR_FILENO);
+ ffi_define_constant (sc, SEEK_SET);
+ ffi_define_constant (sc, SEEK_CUR);
+ ffi_define_constant (sc, SEEK_END);
+
+ ffi_define_function (sc, sleep);
+ ffi_define_function (sc, usleep);
+ ffi_define_function (sc, chdir);
+ ffi_define_function (sc, strerror);
+ ffi_define_function (sc, getenv);
+ ffi_define_function (sc, setenv);
+ ffi_define_function_name (sc, "_exit", exit);
+ ffi_define_function (sc, open);
+ ffi_define_function (sc, fdopen);
+ ffi_define_function (sc, close);
+ ffi_define_function (sc, seek);
+ ffi_define_function (sc, get_temp_path);
+ ffi_define_function_name (sc, "_mkdtemp", mkdtemp);
+ ffi_define_function (sc, unlink);
+ ffi_define_function (sc, unlink_recursively);
+ ffi_define_function (sc, rename);
+ ffi_define_function (sc, getcwd);
+ ffi_define_function (sc, mkdir);
+ ffi_define_function (sc, rmdir);
+ ffi_define_function (sc, get_isotime);
+ ffi_define_function (sc, get_time);
+ ffi_define_function (sc, getpid);
+
+ /* Random numbers. */
+ ffi_define_function (sc, srandom);
+ ffi_define_function (sc, random);
+ ffi_define_function (sc, make_random_string);
+
+ /* Process management. */
+ ffi_define_function (sc, spawn_process);
+ ffi_define_function (sc, spawn_process_fd);
+ ffi_define_function (sc, wait_process);
+ ffi_define_function (sc, wait_processes);
+ ffi_define_function (sc, pipe);
+ ffi_define_function (sc, inbound_pipe);
+ ffi_define_function (sc, outbound_pipe);
+
+ /* estream functions. */
+ ffi_define_function_name (sc, "es-fclose", es_fclose);
+ ffi_define_function_name (sc, "es-read", es_read);
+ ffi_define_function_name (sc, "es-feof", es_feof);
+ ffi_define_function_name (sc, "es-write", es_write);
+
+ /* Test helper functions. */
+ ffi_define_function (sc, file_equal);
+ ffi_define_function (sc, splice);
+ ffi_define_function (sc, string_index);
+ ffi_define_function (sc, string_rindex);
+ ffi_define_function_name (sc, "string-contains?", string_contains);
+
+ /* User interface. */
+ ffi_define_function (sc, flush_stdio);
+ ffi_define_function (sc, prompt);
+
+ /* Configuration. */
+ ffi_define_function_name (sc, "*verbose*", get_verbose);
+ ffi_define_function_name (sc, "*set-verbose!*", set_verbose);
+
+ ffi_define (sc, "*argv0*", sc->vptr->mk_string (sc, argv0));
+ ffi_define (sc, "*scriptname*", sc->vptr->mk_string (sc, scriptname));
+ for (i = argc - 1; i >= 0; i--)
+ {
+ pointer value = sc->vptr->mk_string (sc, argv[i]);
+ args = (sc->vptr->cons) (sc, value, args);
+ }
+ ffi_define (sc, "*args*", args);
+
+#if _WIN32
+ ffi_define (sc, "*pathsep*", sc->vptr->mk_character (sc, ';'));
+#else
+ ffi_define (sc, "*pathsep*", sc->vptr->mk_character (sc, ':'));
+#endif
+
+ ffi_define (sc, "*win32*",
+#if _WIN32
+ sc->T
+#else
+ sc->F
+#endif
+ );
+
+ ffi_define (sc, "*maintainer-mode*",
+#if MAINTAINER_MODE
+ sc->T
+#else
+ sc->F
+#endif
+ );
+
+ ffi_define (sc, "*run-all-tests*",
+#if RUN_ALL_TESTS
+ sc->T
+#else
+ sc->F
+#endif
+ );
+
+
+ ffi_define (sc, "*stdin*",
+ sc->vptr->mk_port_from_file (sc, stdin, port_input));
+ ffi_define (sc, "*stdout*",
+ sc->vptr->mk_port_from_file (sc, stdout, port_output));
+ ffi_define (sc, "*stderr*",
+ sc->vptr->mk_port_from_file (sc, stderr, port_output));
+
+ return 0;
+}
diff --git a/tests/gpgscm/ffi.h b/tests/gpgscm/ffi.h
new file mode 100644
index 0000000..eba6282
--- /dev/null
+++ b/tests/gpgscm/ffi.h
@@ -0,0 +1,30 @@
+/* FFI interface for TinySCHEME.
+ *
+ * Copyright (C) 2016 g10 code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef GPGSCM_FFI_H
+#define GPGSCM_FFI_H
+
+#include <gpg-error.h>
+#include "scheme.h"
+
+gpg_error_t ffi_init (scheme *sc, const char *argv0, const char *scriptname,
+ int argc, const char **argv);
+
+#endif /* GPGSCM_FFI_H */
diff --git a/tests/gpgscm/ffi.scm b/tests/gpgscm/ffi.scm
new file mode 100644
index 0000000..051c2c2
--- /dev/null
+++ b/tests/gpgscm/ffi.scm
@@ -0,0 +1,51 @@
+;; FFI interface for TinySCHEME.
+;;
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+;; Foreign function wrapper. Expects F to return a list with the
+;; first element being the `error_t' value returned by the foreign
+;; function. The error is thrown, or the cdr of the result is
+;; returned.
+(define (ffi-apply name f args)
+ (let ((result (apply f args)))
+ (cond
+ ((string? result)
+ (ffi-fail name args result))
+ ((not (= (car result) 0))
+ (ffi-fail name args (strerror (car result))))
+ ((and (= (car result) 0) (pair? (cdr result))) (cadr result))
+ ((= (car result) 0) '())
+ (else
+ (throw (list "Result violates FFI calling convention: " result))))))
+
+(define (ffi-fail name args message)
+ (let ((args' (open-output-string)))
+ (write (cons (string->symbol name) args) args')
+ (throw (get-output-string args') message)))
+
+;; Pseudo-definitions for foreign functions. Evaluates to no code,
+;; but serves as documentation.
+(macro (ffi-define form))
+
+;; Runtime support.
+
+;; Low-level mechanism to terminate the process.
+(ffi-define (_exit status))
+
+;; Get the current time in seconds since the epoch.
+(ffi-define (get-time))
diff --git a/tests/gpgscm/gnupg.scm b/tests/gpgscm/gnupg.scm
new file mode 100644
index 0000000..77bf479
--- /dev/null
+++ b/tests/gpgscm/gnupg.scm
@@ -0,0 +1,49 @@
+;; Common definitions for executing gpg and related tools.
+;;
+;; Copyright (C) 2016, 2017 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+;; Evaluate a sequence of expressions with the given home directory.
+(define-macro (with-home-directory gnupghome . expressions)
+ (let ((original-home-directory (gensym)))
+ `(let ((,original-home-directory (getenv "GNUPGHOME")))
+ (dynamic-wind
+ (lambda () (setenv "GNUPGHOME" ,gnupghome #t))
+ (lambda () ,@expressions)
+ (lambda () (setenv "GNUPGHOME" ,original-home-directory #t))))))
+
+;; Evaluate a sequence of expressions with an ephemeral home
+;; directory.
+(define-macro (with-ephemeral-home-directory setup-fn teardown-fn . expressions)
+ (let ((original-home-directory (gensym))
+ (ephemeral-home-directory (gensym))
+ (setup (gensym))
+ (teardown (gensym)))
+ `(let ((,original-home-directory (getenv "GNUPGHOME"))
+ (,ephemeral-home-directory (mkdtemp))
+ (,setup (delay (,setup-fn)))
+ (,teardown (delay (,teardown-fn))))
+ (finally (unlink-recursively ,ephemeral-home-directory)
+ (dynamic-wind
+ (lambda ()
+ (setenv "GNUPGHOME" ,ephemeral-home-directory #t)
+ (with-working-directory ,ephemeral-home-directory (force ,setup)))
+ (lambda () ,@expressions)
+ (lambda ()
+ (setenv "GNUPGHOME" ,ephemeral-home-directory #t)
+ (with-working-directory ,ephemeral-home-directory (force ,teardown))
+ (setenv "GNUPGHOME" ,original-home-directory #t)))))))
diff --git a/tests/gpgscm/init.scm b/tests/gpgscm/init.scm
new file mode 100644
index 0000000..66bec0f
--- /dev/null
+++ b/tests/gpgscm/init.scm
@@ -0,0 +1,823 @@
+; Initialization file for TinySCHEME 1.41
+
+; Per R5RS, up to four deep compositions should be defined
+(define (caar x) (car (car x)))
+(define (cadr x) (car (cdr x)))
+(define (cdar x) (cdr (car x)))
+(define (cddr x) (cdr (cdr x)))
+(define (caaar x) (car (car (car x))))
+(define (caadr x) (car (car (cdr x))))
+(define (cadar x) (car (cdr (car x))))
+(define (caddr x) (car (cdr (cdr x))))
+(define (cdaar x) (cdr (car (car x))))
+(define (cdadr x) (cdr (car (cdr x))))
+(define (cddar x) (cdr (cdr (car x))))
+(define (cdddr x) (cdr (cdr (cdr x))))
+(define (caaaar x) (car (car (car (car x)))))
+(define (caaadr x) (car (car (car (cdr x)))))
+(define (caadar x) (car (car (cdr (car x)))))
+(define (caaddr x) (car (car (cdr (cdr x)))))
+(define (cadaar x) (car (cdr (car (car x)))))
+(define (cadadr x) (car (cdr (car (cdr x)))))
+(define (caddar x) (car (cdr (cdr (car x)))))
+(define (cadddr x) (car (cdr (cdr (cdr x)))))
+(define (cdaaar x) (cdr (car (car (car x)))))
+(define (cdaadr x) (cdr (car (car (cdr x)))))
+(define (cdadar x) (cdr (car (cdr (car x)))))
+(define (cdaddr x) (cdr (car (cdr (cdr x)))))
+(define (cddaar x) (cdr (cdr (car (car x)))))
+(define (cddadr x) (cdr (cdr (car (cdr x)))))
+(define (cdddar x) (cdr (cdr (cdr (car x)))))
+(define (cddddr x) (cdr (cdr (cdr (cdr x)))))
+
+;;;; Utility to ease macro creation
+(define (macro-expand form)
+ ((eval (get-closure-code (eval (car form)))) form))
+
+(define (macro-expand-all form)
+ (if (macro? form)
+ (macro-expand-all (macro-expand form))
+ form))
+
+(define *compile-hook* macro-expand-all)
+
+
+(macro (unless form)
+ `(if (not ,(cadr form)) (begin ,@(cddr form))))
+
+(macro (when form)
+ `(if ,(cadr form) (begin ,@(cddr form))))
+
+; DEFINE-MACRO Contributed by Andy Gaynor
+(macro (define-macro dform)
+ (if (symbol? (cadr dform))
+ `(macro ,@(cdr dform))
+ (let ((form (gensym)))
+ `(macro (,(caadr dform) ,form)
+ (apply (lambda ,(cdadr dform) ,@(cddr dform)) (cdr ,form))))))
+
+; Utilities for math. Notice that inexact->exact is primitive,
+; but exact->inexact is not.
+(define exact? integer?)
+(define (inexact? x) (and (real? x) (not (integer? x))))
+(define (even? n) (= (remainder n 2) 0))
+(define (odd? n) (not (= (remainder n 2) 0)))
+(define (zero? n) (= n 0))
+(define (positive? n) (> n 0))
+(define (negative? n) (< n 0))
+(define complex? number?)
+(define rational? real?)
+(define (abs n) (if (>= n 0) n (- n)))
+(define (exact->inexact n) (* n 1.0))
+(define (<> n1 n2) (not (= n1 n2)))
+
+; min and max must return inexact if any arg is inexact; use (+ n 0.0)
+(define (max . lst)
+ (foldr (lambda (a b)
+ (if (> a b)
+ (if (exact? b) a (+ a 0.0))
+ (if (exact? a) b (+ b 0.0))))
+ (car lst) (cdr lst)))
+(define (min . lst)
+ (foldr (lambda (a b)
+ (if (< a b)
+ (if (exact? b) a (+ a 0.0))
+ (if (exact? a) b (+ b 0.0))))
+ (car lst) (cdr lst)))
+
+(define (succ x) (+ x 1))
+(define (pred x) (- x 1))
+(define gcd
+ (lambda a
+ (if (null? a)
+ 0
+ (let ((aa (abs (car a)))
+ (bb (abs (cadr a))))
+ (if (= bb 0)
+ aa
+ (gcd bb (remainder aa bb)))))))
+(define lcm
+ (lambda a
+ (if (null? a)
+ 1
+ (let ((aa (abs (car a)))
+ (bb (abs (cadr a))))
+ (if (or (= aa 0) (= bb 0))
+ 0
+ (abs (* (quotient aa (gcd aa bb)) bb)))))))
+
+
+(define (string . charlist)
+ (list->string charlist))
+
+(define (list->string charlist)
+ (let* ((len (length charlist))
+ (newstr (make-string len))
+ (fill-string!
+ (lambda (str i len charlist)
+ (if (= i len)
+ str
+ (begin (string-set! str i (car charlist))
+ (fill-string! str (+ i 1) len (cdr charlist)))))))
+ (fill-string! newstr 0 len charlist)))
+
+(define (string-fill! s e)
+ (let ((n (string-length s)))
+ (let loop ((i 0))
+ (if (= i n)
+ s
+ (begin (string-set! s i e) (loop (succ i)))))))
+
+(define (string->list s)
+ (let loop ((n (pred (string-length s))) (l '()))
+ (if (= n -1)
+ l
+ (loop (pred n) (cons (string-ref s n) l)))))
+
+(define (string-copy str)
+ (string-append str))
+
+(define (string->anyatom str pred)
+ (let* ((a (string->atom str)))
+ (if (pred a) a
+ (error "string->xxx: not a xxx" a))))
+
+(define (string->number str . base)
+ (let ((n (string->atom str (if (null? base) 10 (car base)))))
+ (if (number? n) n #f)))
+
+(define (anyatom->string n pred)
+ (if (pred n)
+ (atom->string n)
+ (error "xxx->string: not a xxx" n)))
+
+(define (number->string n . base)
+ (atom->string n (if (null? base) 10 (car base))))
+
+
+(define (char-cmp? cmp a b)
+ (cmp (char->integer a) (char->integer b)))
+(define (char-ci-cmp? cmp a b)
+ (cmp (char->integer (char-downcase a)) (char->integer (char-downcase b))))
+
+(define (char=? a b) (char-cmp? = a b))
+(define (char<? a b) (char-cmp? < a b))
+(define (char>? a b) (char-cmp? > a b))
+(define (char<=? a b) (char-cmp? <= a b))
+(define (char>=? a b) (char-cmp? >= a b))
+
+(define (char-ci=? a b) (char-ci-cmp? = a b))
+(define (char-ci<? a b) (char-ci-cmp? < a b))
+(define (char-ci>? a b) (char-ci-cmp? > a b))
+(define (char-ci<=? a b) (char-ci-cmp? <= a b))
+(define (char-ci>=? a b) (char-ci-cmp? >= a b))
+
+; Note the trick of returning (cmp x y)
+(define (string-cmp? chcmp cmp a b)
+ (let ((na (string-length a)) (nb (string-length b)))
+ (let loop ((i 0))
+ (cond
+ ((= i na)
+ (if (= i nb) (cmp 0 0) (cmp 0 1)))
+ ((= i nb)
+ (cmp 1 0))
+ ((chcmp = (string-ref a i) (string-ref b i))
+ (loop (succ i)))
+ (else
+ (chcmp cmp (string-ref a i) (string-ref b i)))))))
+
+
+(define (string=? a b) (string-cmp? char-cmp? = a b))
+(define (string<? a b) (string-cmp? char-cmp? < a b))
+(define (string>? a b) (string-cmp? char-cmp? > a b))
+(define (string<=? a b) (string-cmp? char-cmp? <= a b))
+(define (string>=? a b) (string-cmp? char-cmp? >= a b))
+
+(define (string-ci=? a b) (string-cmp? char-ci-cmp? = a b))
+(define (string-ci<? a b) (string-cmp? char-ci-cmp? < a b))
+(define (string-ci>? a b) (string-cmp? char-ci-cmp? > a b))
+(define (string-ci<=? a b) (string-cmp? char-ci-cmp? <= a b))
+(define (string-ci>=? a b) (string-cmp? char-ci-cmp? >= a b))
+
+(define (list . x) x)
+
+(define (foldr f x lst)
+ (if (null? lst)
+ x
+ (foldr f (f x (car lst)) (cdr lst))))
+
+(define (unzip1-with-cdr . lists)
+ (unzip1-with-cdr-iterative lists '() '()))
+
+(define (unzip1-with-cdr-iterative lists cars cdrs)
+ (if (null? lists)
+ (cons cars cdrs)
+ (let ((car1 (caar lists))
+ (cdr1 (cdar lists)))
+ (unzip1-with-cdr-iterative
+ (cdr lists)
+ (append cars (list car1))
+ (append cdrs (list cdr1))))))
+
+(define (map proc . lists)
+ (if (null? lists)
+ (apply proc)
+ (if (null? (car lists))
+ '()
+ (let* ((unz (apply unzip1-with-cdr lists))
+ (cars (car unz))
+ (cdrs (cdr unz)))
+ (cons (apply proc cars) (apply map (cons proc cdrs)))))))
+
+(define (for-each proc . lists)
+ (if (null? lists)
+ (apply proc)
+ (if (null? (car lists))
+ #t
+ (let* ((unz (apply unzip1-with-cdr lists))
+ (cars (car unz))
+ (cdrs (cdr unz)))
+ (apply proc cars) (apply map (cons proc cdrs))))))
+
+(define (list-tail x k)
+ (if (zero? k)
+ x
+ (list-tail (cdr x) (- k 1))))
+
+(define (list-ref x k)
+ (car (list-tail x k)))
+
+(define (last-pair x)
+ (if (pair? (cdr x))
+ (last-pair (cdr x))
+ x))
+
+(define (head stream) (car stream))
+
+(define (tail stream) (force (cdr stream)))
+
+(define (vector-equal? x y)
+ (and (vector? x) (vector? y) (= (vector-length x) (vector-length y))
+ (let ((n (vector-length x)))
+ (let loop ((i 0))
+ (if (= i n)
+ #t
+ (and (equal? (vector-ref x i) (vector-ref y i))
+ (loop (succ i))))))))
+
+(define (list->vector x)
+ (apply vector x))
+
+(define (vector-fill! v e)
+ (let ((n (vector-length v)))
+ (let loop ((i 0))
+ (if (= i n)
+ v
+ (begin (vector-set! v i e) (loop (succ i)))))))
+
+(define (vector->list v)
+ (let loop ((n (pred (vector-length v))) (l '()))
+ (if (= n -1)
+ l
+ (loop (pred n) (cons (vector-ref v n) l)))))
+
+;; The following quasiquote macro is due to Eric S. Tiedemann.
+;; Copyright 1988 by Eric S. Tiedemann; all rights reserved.
+;;
+;; Subsequently modified to handle vectors: D. Souflis
+
+(macro
+ quasiquote
+ (lambda (l)
+ (define (mcons f l r)
+ (if (and (pair? r)
+ (eq? (car r) 'quote)
+ (eq? (car (cdr r)) (cdr f))
+ (pair? l)
+ (eq? (car l) 'quote)
+ (eq? (car (cdr l)) (car f)))
+ (if (or (procedure? f) (number? f) (string? f))
+ f
+ (list 'quote f))
+ (if (eqv? l vector)
+ (apply l (eval r))
+ (list 'cons l r)
+ )))
+ (define (mappend f l r)
+ (if (or (null? (cdr f))
+ (and (pair? r)
+ (eq? (car r) 'quote)
+ (eq? (car (cdr r)) '())))
+ l
+ (list 'append l r)))
+ (define (foo level form)
+ (cond ((not (pair? form))
+ (if (or (procedure? form) (number? form) (string? form))
+ form
+ (list 'quote form))
+ )
+ ((eq? 'quasiquote (car form))
+ (mcons form ''quasiquote (foo (+ level 1) (cdr form))))
+ (#t (if (zero? level)
+ (cond ((eq? (car form) 'unquote) (car (cdr form)))
+ ((eq? (car form) 'unquote-splicing)
+ (error "Unquote-splicing wasn't in a list:"
+ form))
+ ((and (pair? (car form))
+ (eq? (car (car form)) 'unquote-splicing))
+ (mappend form (car (cdr (car form)))
+ (foo level (cdr form))))
+ (#t (mcons form (foo level (car form))
+ (foo level (cdr form)))))
+ (cond ((eq? (car form) 'unquote)
+ (mcons form ''unquote (foo (- level 1)
+ (cdr form))))
+ ((eq? (car form) 'unquote-splicing)
+ (mcons form ''unquote-splicing
+ (foo (- level 1) (cdr form))))
+ (#t (mcons form (foo level (car form))
+ (foo level (cdr form)))))))))
+ (foo 0 (car (cdr l)))))
+
+;;;;;Helper for the dynamic-wind definition. By Tom Breton (Tehom)
+(define (shared-tail x y)
+ (let ((len-x (length x))
+ (len-y (length y)))
+ (define (shared-tail-helper x y)
+ (if
+ (eq? x y)
+ x
+ (shared-tail-helper (cdr x) (cdr y))))
+
+ (cond
+ ((> len-x len-y)
+ (shared-tail-helper
+ (list-tail x (- len-x len-y))
+ y))
+ ((< len-x len-y)
+ (shared-tail-helper
+ x
+ (list-tail y (- len-y len-x))))
+ (#t (shared-tail-helper x y)))))
+
+;;;;;Dynamic-wind by Tom Breton (Tehom)
+
+;;Guarded because we must only eval this once, because doing so
+;;redefines call/cc in terms of old call/cc
+(unless (defined? 'dynamic-wind)
+ (let
+ ;;These functions are defined in the context of a private list of
+ ;;pairs of before/after procs.
+ ( (*active-windings* '())
+ ;;We'll define some functions into the larger environment, so
+ ;;we need to know it.
+ (outer-env (current-environment)))
+
+ ;;Poor-man's structure operations
+ (define before-func car)
+ (define after-func cdr)
+ (define make-winding cons)
+
+ ;;Manage active windings
+ (define (activate-winding! new)
+ ((before-func new))
+ (set! *active-windings* (cons new *active-windings*)))
+ (define (deactivate-top-winding!)
+ (let ((old-top (car *active-windings*)))
+ ;;Remove it from the list first so it's not active during its
+ ;;own exit.
+ (set! *active-windings* (cdr *active-windings*))
+ ((after-func old-top))))
+
+ (define (set-active-windings! new-ws)
+ (unless (eq? new-ws *active-windings*)
+ (let ((shared (shared-tail new-ws *active-windings*)))
+
+ ;;Define the looping functions.
+ ;;Exit the old list. Do deeper ones last. Don't do
+ ;;any shared ones.
+ (define (pop-many)
+ (unless (eq? *active-windings* shared)
+ (deactivate-top-winding!)
+ (pop-many)))
+ ;;Enter the new list. Do deeper ones first so that the
+ ;;deeper windings will already be active. Don't do any
+ ;;shared ones.
+ (define (push-many new-ws)
+ (unless (eq? new-ws shared)
+ (push-many (cdr new-ws))
+ (activate-winding! (car new-ws))))
+
+ ;;Do it.
+ (pop-many)
+ (push-many new-ws))))
+
+ ;;The definitions themselves.
+ (eval
+ `(define call-with-current-continuation
+ ;;It internally uses the built-in call/cc, so capture it.
+ ,(let ((old-c/cc call-with-current-continuation))
+ (lambda (func)
+ ;;Use old call/cc to get the continuation.
+ (old-c/cc
+ (lambda (continuation)
+ ;;Call func with not the continuation itself
+ ;;but a procedure that adjusts the active
+ ;;windings to what they were when we made
+ ;;this, and only then calls the
+ ;;continuation.
+ (func
+ (let ((current-ws *active-windings*))
+ (lambda (x)
+ (set-active-windings! current-ws)
+ (continuation x)))))))))
+ outer-env)
+ ;;We can't just say "define (dynamic-wind before thunk after)"
+ ;;because the lambda it's defined to lives in this environment,
+ ;;not in the global environment.
+ (eval
+ `(define dynamic-wind
+ ,(lambda (before thunk after)
+ ;;Make a new winding
+ (activate-winding! (make-winding before after))
+ (let ((result (thunk)))
+ ;;Get rid of the new winding.
+ (deactivate-top-winding!)
+ ;;The return value is that of thunk.
+ result)))
+ outer-env)))
+
+(define call/cc call-with-current-continuation)
+
+
+;;;;; atom? and equal? written by a.k
+
+;;;; atom?
+(define (atom? x)
+ (not (pair? x)))
+
+;;;; equal?
+(define (equal? x y)
+ (cond
+ ((pair? x)
+ (and (pair? y)
+ (equal? (car x) (car y))
+ (equal? (cdr x) (cdr y))))
+ ((vector? x)
+ (and (vector? y) (vector-equal? x y)))
+ ((string? x)
+ (and (string? y) (string=? x y)))
+ (else (eqv? x y))))
+
+;;;; (do ((var init inc) ...) (endtest result ...) body ...)
+;;
+(macro do
+ (lambda (do-macro)
+ (apply (lambda (do vars endtest . body)
+ (let ((do-loop (gensym)))
+ `(letrec ((,do-loop
+ (lambda ,(map (lambda (x)
+ (if (pair? x) (car x) x))
+ `,vars)
+ (if ,(car endtest)
+ (begin ,@(cdr endtest))
+ (begin
+ ,@body
+ (,do-loop
+ ,@(map (lambda (x)
+ (cond
+ ((not (pair? x)) x)
+ ((< (length x) 3) (car x))
+ (else (car (cdr (cdr x))))))
+ `,vars)))))))
+ (,do-loop
+ ,@(map (lambda (x)
+ (if (and (pair? x) (cdr x))
+ (car (cdr x))
+ '()))
+ `,vars)))))
+ do-macro)))
+
+;;;; generic-member
+(define (generic-member cmp obj lst)
+ (cond
+ ((null? lst) #f)
+ ((cmp obj (car lst)) lst)
+ (else (generic-member cmp obj (cdr lst)))))
+
+(define (memq obj lst)
+ (generic-member eq? obj lst))
+(define (memv obj lst)
+ (generic-member eqv? obj lst))
+(define (member obj lst)
+ (generic-member equal? obj lst))
+
+;;;; generic-assoc
+(define (generic-assoc cmp obj alst)
+ (cond
+ ((null? alst) #f)
+ ((cmp obj (caar alst)) (car alst))
+ (else (generic-assoc cmp obj (cdr alst)))))
+
+(define (assq obj alst)
+ (generic-assoc eq? obj alst))
+(define (assv obj alst)
+ (generic-assoc eqv? obj alst))
+(define (assoc obj alst)
+ (generic-assoc equal? obj alst))
+
+(define (acons x y z) (cons (cons x y) z))
+
+;;;; Handy for imperative programs
+;;;; Used as: (define-with-return (foo x y) .... (return z) ...)
+(macro (define-with-return form)
+ `(define ,(cadr form)
+ (call/cc (lambda (return) ,@(cddr form)))))
+
+;; Print the given history.
+(define (vm-history-print history)
+ (let loop ((n 0) (skip 0) (frames history))
+ (cond
+ ((null? frames)
+ #t)
+ ((> skip 0)
+ (loop 0 (- skip 1) (cdr frames)))
+ (else
+ (let ((f (car frames)))
+ (display n)
+ (display ": ")
+ (let ((tag (get-tag f)))
+ (when (and (pair? tag) (string? (car tag)) (number? (cdr tag)))
+ (display (basename (car tag)))
+ (display ":")
+ (display (+ 1 (cdr tag)))
+ (display ": ")))
+ (write f))
+ (newline)
+ (loop (+ n 1) skip (cdr frames))))))
+
+;;;; Simple exception handling
+;
+; Exceptions are caught as follows:
+;
+; (catch (do-something to-recover and-return meaningful-value)
+; (if-something goes-wrong)
+; (with-these calls))
+;
+; "Catch" establishes a scope spanning multiple call-frames until
+; another "catch" is encountered. Within the recovery expression
+; the thrown exception is bound to *error*. Errors can be rethrown
+; using (rethrow *error*).
+;
+; Finalization can be expressed using "finally":
+;
+; (finally (finalize-something called-purely-for side-effects)
+; (whether-or-not something goes-wrong)
+; (with-these calls))
+;
+; The final expression is executed purely for its side-effects,
+; both when the function exits successfully, and when an exception
+; is thrown.
+;
+; Exceptions are thrown with:
+;
+; (throw "message")
+;
+; If used outside a (catch ...), reverts to (error "message")
+
+(define *handlers* (list))
+
+(define (push-handler proc)
+ (set! *handlers* (cons proc *handlers*)))
+
+(define (pop-handler)
+ (let ((h (car *handlers*)))
+ (set! *handlers* (cdr *handlers*))
+ h))
+
+(define (more-handlers?)
+ (pair? *handlers*))
+
+;; This throws an exception.
+(define (throw message . args)
+ (throw' message args (cdr (*vm-history*))))
+
+;; This is used by the vm to throw exceptions.
+(define (throw' message args history)
+ (cond
+ ((and args (list? args) (= 2 (length args))
+ (equal? *interpreter-exit* (car args)))
+ (*run-atexit-handlers*)
+ (quit (cadr args)))
+ ((more-handlers?)
+ ((pop-handler) message args history))
+ (else
+ (display message)
+ (when (and args (not (null? args)))
+ (display ": ")
+ (if (and (pair? args) (string? (car args)))
+ (begin (display (car args))
+ (unless (null? (cdr args))
+ (newline)
+ (write (cdr args))))
+ (write args)))
+ (newline)
+ (vm-history-print history)
+ (quit 1))))
+
+;; Convenience function to rethrow the error.
+(define (rethrow e)
+ (apply throw' e))
+
+(macro (catch form)
+ (let ((label (gensym)))
+ `(call/cc (lambda (**exit**)
+ (push-handler (lambda *error* (**exit** ,(cadr form))))
+ (let ((,label (begin ,@(cddr form))))
+ (pop-handler)
+ ,label)))))
+
+(define-macro (finally final-expression . expressions)
+ (let ((result (gensym)))
+ `(let ((,result (catch (begin ,final-expression (rethrow *error*))
+ ,@expressions)))
+ ,final-expression
+ ,result)))
+
+;; Make the vm use throw'.
+(define *error-hook* throw')
+
+
+
+;; High-level mechanism to terminate the process is to throw an error
+;; of the form (*interpreter-exit* status). This gives automatic
+;; resource management a chance to clean up.
+(define *interpreter-exit* (gensym))
+
+;; Terminate the process returning STATUS to the parent.
+(define (exit status)
+ (throw "interpreter exit" *interpreter-exit* status))
+
+;; A list of functions run at interpreter shutdown.
+(define *atexit-handlers* (list))
+
+;; Execute all these functions.
+(define (*run-atexit-handlers*)
+ (unless (null? *atexit-handlers*)
+ (let ((proc (car *atexit-handlers*)))
+ ;; Drop proc from the list so that it will not get
+ ;; executed again even if it raises an exception.
+ (set! *atexit-handlers* (cdr *atexit-handlers*))
+ (proc)
+ (*run-atexit-handlers*))))
+
+;; Register a function to be run at interpreter shutdown.
+(define (atexit proc)
+ (set! *atexit-handlers* (cons proc *atexit-handlers*)))
+
+
+
+;;;;; Definition of MAKE-ENVIRONMENT, to be used with two-argument EVAL
+
+(macro (make-environment form)
+ `(apply (lambda ()
+ ,@(cdr form)
+ (current-environment))))
+
+(define-macro (eval-polymorphic x . envl)
+ (display envl)
+ (let* ((env (if (null? envl) (current-environment) (eval (car envl))))
+ (xval (eval x env)))
+ (if (closure? xval)
+ (make-closure (get-closure-code xval) env)
+ xval)))
+
+; Redefine this if you install another package infrastructure
+; Also redefine 'package'
+(define *colon-hook* eval)
+
+(macro (package form)
+ `(apply (lambda ()
+ ,@(cdr form)
+ (current-environment))))
+
+(define-macro (export name . expressions)
+ `(define ,name
+ (begin
+ ,@expressions)))
+
+;;;;; I/O
+
+(define (input-output-port? p)
+ (and (input-port? p) (output-port? p)))
+
+(define (close-port p)
+ (cond
+ ((input-output-port? p) (close-input-port p) (close-output-port p))
+ ((input-port? p) (close-input-port p))
+ ((output-port? p) (close-output-port p))
+ (else (throw "Not a port" p))))
+
+(define (call-with-input-file s p)
+ (let ((inport (open-input-file s)))
+ (if (eq? inport #f)
+ #f
+ (let ((res (p inport)))
+ (close-input-port inport)
+ res))))
+
+(define (call-with-output-file s p)
+ (let ((outport (open-output-file s)))
+ (if (eq? outport #f)
+ #f
+ (let ((res (p outport)))
+ (close-output-port outport)
+ res))))
+
+(define (with-input-from-file s p)
+ (let ((inport (open-input-file s)))
+ (if (eq? inport #f)
+ #f
+ (let ((prev-inport (current-input-port)))
+ (set-input-port inport)
+ (let ((res (p)))
+ (close-input-port inport)
+ (set-input-port prev-inport)
+ res)))))
+
+(define (with-output-to-file s p)
+ (let ((outport (open-output-file s)))
+ (if (eq? outport #f)
+ #f
+ (let ((prev-outport (current-output-port)))
+ (set-output-port outport)
+ (let ((res (p)))
+ (close-output-port outport)
+ (set-output-port prev-outport)
+ res)))))
+
+(define (with-input-output-from-to-files si so p)
+ (let ((inport (open-input-file si))
+ (outport (open-input-file so)))
+ (if (not (and inport outport))
+ (begin
+ (close-input-port inport)
+ (close-output-port outport)
+ #f)
+ (let ((prev-inport (current-input-port))
+ (prev-outport (current-output-port)))
+ (set-input-port inport)
+ (set-output-port outport)
+ (let ((res (p)))
+ (close-input-port inport)
+ (close-output-port outport)
+ (set-input-port prev-inport)
+ (set-output-port prev-outport)
+ res)))))
+
+; Random number generator (maximum cycle)
+(define *seed* 1)
+(define (random-next)
+ (let* ((a 16807) (m 2147483647) (q (quotient m a)) (r (modulo m a)))
+ (set! *seed*
+ (- (* a (- *seed*
+ (* (quotient *seed* q) q)))
+ (* (quotient *seed* q) r)))
+ (if (< *seed* 0) (set! *seed* (+ *seed* m)))
+ *seed*))
+;; SRFI-0
+;; COND-EXPAND
+;; Implemented as a macro
+(define *features* '(srfi-0 tinyscheme))
+
+(define-macro (cond-expand . cond-action-list)
+ (cond-expand-runtime cond-action-list))
+
+(define (cond-expand-runtime cond-action-list)
+ (if (null? cond-action-list)
+ #t
+ (if (cond-eval (caar cond-action-list))
+ `(begin ,@(cdar cond-action-list))
+ (cond-expand-runtime (cdr cond-action-list)))))
+
+(define (cond-eval-and cond-list)
+ (foldr (lambda (x y) (and (cond-eval x) (cond-eval y))) #t cond-list))
+
+(define (cond-eval-or cond-list)
+ (foldr (lambda (x y) (or (cond-eval x) (cond-eval y))) #f cond-list))
+
+(define (cond-eval condition)
+ (cond
+ ((symbol? condition)
+ (if (member condition *features*) #t #f))
+ ((eq? condition #t) #t)
+ ((eq? condition #f) #f)
+ (else (case (car condition)
+ ((and) (cond-eval-and (cdr condition)))
+ ((or) (cond-eval-or (cdr condition)))
+ ((not) (if (not (null? (cddr condition)))
+ (error "cond-expand : 'not' takes 1 argument")
+ (not (cond-eval (cadr condition)))))
+ (else (error "cond-expand : unknown operator" (car condition)))))))
+
+(gc-verbose #f)
diff --git a/tests/gpgscm/lib.scm b/tests/gpgscm/lib.scm
new file mode 100644
index 0000000..258f692
--- /dev/null
+++ b/tests/gpgscm/lib.scm
@@ -0,0 +1,307 @@
+;; Additional library functions for TinySCHEME.
+;;
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(macro (assert form)
+ (let ((tag (get-tag form)))
+ `(if (not ,(cadr form))
+ (throw ,(if (and (pair? tag) (string? (car tag)) (number? (cdr tag)))
+ `(string-append ,(car tag) ":"
+ ,(number->string (+ 1 (cdr tag)))
+ ": Assertion failed: ")
+ "Assertion failed: ")
+ (quote ,(cadr form))))))
+(assert #t)
+(assert (not #f))
+
+;; Trace displays and returns the given value. A debugging aid.
+(define (trace x)
+ (display x)
+ (newline)
+ x)
+
+;; Stringification.
+(define (stringify expression)
+ (let ((p (open-output-string)))
+ (write expression p)
+ (get-output-string p)))
+
+(define (filter pred lst)
+ (cond ((null? lst) '())
+ ((pred (car lst))
+ (cons (car lst) (filter pred (cdr lst))))
+ (else (filter pred (cdr lst)))))
+
+(define (any p l)
+ (cond ((null? l) #f)
+ ((p (car l)) #t)
+ (else (any p (cdr l)))))
+
+(define (all p l)
+ (cond ((null? l) #t)
+ ((not (p (car l))) #f)
+ (else (all p (cdr l)))))
+
+;; Return the first element of a list.
+(define first car)
+
+;; Return the last element of a list.
+(define (last lst)
+ (if (null? (cdr lst))
+ (car lst)
+ (last (cdr lst))))
+
+;; Compute the powerset of a list.
+(define (powerset set)
+ (if (null? set)
+ '(())
+ (let ((rst (powerset (cdr set))))
+ (append (map (lambda (x) (cons (car set) x))
+ rst)
+ rst))))
+
+;; Is PREFIX a prefix of S?
+(define (string-prefix? s prefix)
+ (and (>= (string-length s) (string-length prefix))
+ (string=? prefix (substring s 0 (string-length prefix)))))
+(assert (string-prefix? "Scheme" "Sch"))
+
+;; Is SUFFIX a suffix of S?
+(define (string-suffix? s suffix)
+ (and (>= (string-length s) (string-length suffix))
+ (string=? suffix (substring s (- (string-length s)
+ (string-length suffix))
+ (string-length s)))))
+(assert (string-suffix? "Scheme" "eme"))
+
+;; Locate the first occurrence of needle in haystack starting at offset.
+(ffi-define (string-index haystack needle [offset]))
+(assert (= 2 (string-index "Hallo" #\l)))
+(assert (= 3 (string-index "Hallo" #\l 3)))
+(assert (equal? #f (string-index "Hallo" #\.)))
+
+;; Locate the last occurrence of needle in haystack starting at offset.
+(ffi-define (string-rindex haystack needle [offset]))
+(assert (= 3 (string-rindex "Hallo" #\l)))
+(assert (equal? #f (string-rindex "Hallo" #\a 2)))
+(assert (equal? #f (string-rindex "Hallo" #\.)))
+
+;; Split HAYSTACK at each character that makes PREDICATE true at most
+;; N times.
+(define (string-split-pln haystack predicate lookahead n)
+ (let ((length (string-length haystack)))
+ (define (split acc offset n)
+ (if (>= offset length)
+ (reverse! acc)
+ (let ((i (lookahead haystack offset)))
+ (if (or (eq? i #f) (= 0 n))
+ (reverse! (cons (substring haystack offset length) acc))
+ (split (cons (substring haystack offset i) acc)
+ (+ i 1) (- n 1))))))
+ (split '() 0 n)))
+
+(define (string-indexp haystack offset predicate)
+ (cond
+ ((= (string-length haystack) offset)
+ #f)
+ ((predicate (string-ref haystack offset))
+ offset)
+ (else
+ (string-indexp haystack (+ 1 offset) predicate))))
+
+;; Split HAYSTACK at each character that makes PREDICATE true at most
+;; N times.
+(define (string-splitp haystack predicate n)
+ (string-split-pln haystack predicate
+ (lambda (haystack offset)
+ (string-indexp haystack offset predicate))
+ n))
+(assert (equal? '("a" "b") (string-splitp "a b" char-whitespace? -1)))
+(assert (equal? '("a" "b") (string-splitp "a\tb" char-whitespace? -1)))
+(assert (equal? '("a" "" "b") (string-splitp "a \tb" char-whitespace? -1)))
+
+;; Split haystack at delimiter at most n times.
+(define (string-splitn haystack delimiter n)
+ (string-split-pln haystack
+ (lambda (c) (char=? c delimiter))
+ (lambda (haystack offset)
+ (string-index haystack delimiter offset))
+ n))
+(assert (= 2 (length (string-splitn "foo:bar:baz" #\: 1))))
+(assert (string=? "foo" (car (string-splitn "foo:bar:baz" #\: 1))))
+(assert (string=? "bar:baz" (cadr (string-splitn "foo:bar:baz" #\: 1))))
+
+;; Split haystack at delimiter.
+(define (string-split haystack delimiter)
+ (string-splitn haystack delimiter -1))
+(assert (= 3 (length (string-split "foo:bar:baz" #\:))))
+(assert (string=? "foo" (car (string-split "foo:bar:baz" #\:))))
+(assert (string=? "bar" (cadr (string-split "foo:bar:baz" #\:))))
+(assert (string=? "baz" (caddr (string-split "foo:bar:baz" #\:))))
+
+;; Split haystack at newlines.
+(define (string-split-newlines haystack)
+ (if *win32*
+ (map (lambda (line) (if (string-suffix? line "\r")
+ (substring line 0 (- (string-length line) 1))
+ line))
+ (string-split haystack #\newline))
+ (string-split haystack #\newline)))
+
+;; Trim the prefix of S containing only characters that make PREDICATE
+;; true.
+(define (string-ltrim predicate s)
+ (if (string=? s "")
+ ""
+ (let loop ((s' (string->list s)))
+ (if (predicate (car s'))
+ (loop (cdr s'))
+ (list->string s')))))
+(assert (string=? "" (string-ltrim char-whitespace? "")))
+(assert (string=? "foo" (string-ltrim char-whitespace? " foo")))
+
+;; Trim the suffix of S containing only characters that make PREDICATE
+;; true.
+(define (string-rtrim predicate s)
+ (if (string=? s "")
+ ""
+ (let loop ((s' (reverse! (string->list s))))
+ (if (predicate (car s'))
+ (loop (cdr s'))
+ (list->string (reverse! s'))))))
+(assert (string=? "" (string-rtrim char-whitespace? "")))
+(assert (string=? "foo" (string-rtrim char-whitespace? "foo ")))
+
+;; Trim both the prefix and suffix of S containing only characters
+;; that make PREDICATE true.
+(define (string-trim predicate s)
+ (string-ltrim predicate (string-rtrim predicate s)))
+(assert (string=? "" (string-trim char-whitespace? "")))
+(assert (string=? "foo" (string-trim char-whitespace? " foo ")))
+
+;; Check if needle is contained in haystack.
+(ffi-define (string-contains? haystack needle))
+(assert (string-contains? "Hallo" "llo"))
+(assert (not (string-contains? "Hallo" "olla")))
+
+;; Translate characters.
+(define (string-translate s from to)
+ (list->string (map (lambda (c)
+ (let ((i (string-index from c)))
+ (if i (string-ref to i) c))) (string->list s))))
+(assert (equal? (string-translate "foo/bar" "/" ".") "foo.bar"))
+
+;; Read a word from port P.
+(define (read-word . p)
+ (list->string
+ (let f ()
+ (let ((c (apply peek-char p)))
+ (cond
+ ((eof-object? c) '())
+ ((char-alphabetic? c)
+ (apply read-char p)
+ (cons c (f)))
+ (else
+ (apply read-char p)
+ '()))))))
+
+(define (list->string-reversed lst)
+ (let* ((len (length lst))
+ (str (make-string len)))
+ (let loop ((i (- len 1))
+ (l lst))
+ (if (< i 0)
+ (begin
+ (assert (null? l))
+ str)
+ (begin
+ (string-set! str i (car l))
+ (loop (- i 1) (cdr l)))))))
+
+;; Read a line from port P.
+(define (read-line . p)
+ (let loop ((acc '()))
+ (let ((c (apply peek-char p)))
+ (cond
+ ((eof-object? c)
+ (if (null? acc)
+ c ;; #eof
+ (list->string-reversed acc)))
+ ((char=? c #\newline)
+ (apply read-char p)
+ (list->string-reversed acc))
+ (else
+ (apply read-char p)
+ (loop (cons c acc)))))))
+
+;; Read everything from port P.
+(define (read-all . p)
+ (let loop ((acc (open-output-string)))
+ (let ((c (apply peek-char p)))
+ (cond
+ ((eof-object? c) (get-output-string acc))
+ (else
+ (write-char (apply read-char p) acc)
+ (loop acc))))))
+
+;;
+;; Windows support.
+;;
+
+;; Like call-with-input-file but opens the file in 'binary' mode.
+(define (call-with-binary-input-file filename proc)
+ (letfd ((fd (open filename (logior O_RDONLY O_BINARY))))
+ (proc (fdopen fd "rb"))))
+
+;; Like call-with-output-file but opens the file in 'binary' mode.
+(define (call-with-binary-output-file filename proc)
+ (letfd ((fd (open filename (logior O_WRONLY O_CREAT O_BINARY) #o600)))
+ (proc (fdopen fd "wb"))))
+
+;;
+;; Libc functions.
+;;
+
+;; Change the read/write offset.
+(ffi-define (seek fd offset whence))
+
+;; Constants for WHENCE.
+(ffi-define SEEK_SET)
+(ffi-define SEEK_CUR)
+(ffi-define SEEK_END)
+
+;; Get our process id.
+(ffi-define (getpid))
+
+;; Copy data from file descriptor SOURCE to every file descriptor in
+;; SINKS.
+(ffi-define (splice source . sinks))
+
+;;
+;; Random numbers.
+;;
+
+;; Seed the random number generator.
+(ffi-define (srandom seed))
+
+;; Get a pseudo-random number between 0 (inclusive) and SCALE
+;; (exclusive).
+(ffi-define (random scale))
+
+;; Create a string of the given SIZE containing pseudo-random data.
+(ffi-define (make-random-string size))
diff --git a/tests/gpgscm/main.c b/tests/gpgscm/main.c
new file mode 100644
index 0000000..f2b12aa
--- /dev/null
+++ b/tests/gpgscm/main.c
@@ -0,0 +1,362 @@
+/* TinyScheme-based test driver.
+ *
+ * Copyright (C) 2016 g10 code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <config.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gcrypt.h>
+#include <gpg-error.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#if HAVE_MMAP
+#include <sys/mman.h>
+#endif
+
+#include "private.h"
+#include "scheme.h"
+#include "scheme-private.h"
+#include "ffi.h"
+#include "../common/i18n.h"
+#include "../../common/argparse.h"
+#include "../../common/init.h"
+#include "../../common/logging.h"
+#include "../../common/strlist.h"
+#include "../../common/sysutils.h"
+#include "../../common/util.h"
+
+/* The TinyScheme banner. Unfortunately, it isn't in the header
+ file. */
+#define ts_banner "TinyScheme 1.41"
+
+int verbose;
+
+
+
+/* Constants to identify the commands and options. */
+enum cmd_and_opt_values
+ {
+ aNull = 0,
+ oVerbose = 'v',
+ };
+
+/* The list of commands and options. */
+static ARGPARSE_OPTS opts[] =
+ {
+ ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
+ ARGPARSE_end (),
+ };
+
+char *scmpath = "";
+size_t scmpath_len = 0;
+
+/* Command line parsing. */
+static void
+parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
+{
+
+ while (gnupg_argparse (NULL, pargs, popts))
+ {
+ switch (pargs->r_opt)
+ {
+ case oVerbose:
+ verbose++;
+ break;
+
+ default:
+ pargs->err = ARGPARSE_PRINT_ERROR;
+ break;
+ }
+ }
+}
+
+/* Print usage information and provide strings for help. */
+static const char *
+my_strusage( int level )
+{
+ const char *p;
+
+ switch (level)
+ {
+ case 9: p = "GPL-3.0-or-later"; break;
+ case 11: p = "gpgscm (@GNUPG@)";
+ break;
+ case 13: p = VERSION; break;
+ case 14: p = GNUPG_DEF_COPYRIGHT_LINE; break;
+ case 17: p = PRINTABLE_OS_NAME; break;
+ case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
+
+ case 1:
+ case 40:
+ p = _("Usage: gpgscm [options] [file] (-h for help)");
+ break;
+ case 41:
+ p = _("Syntax: gpgscm [options] [file]\n"
+ "Execute the given Scheme program, or spawn interactive shell.\n");
+ break;
+
+ default: p = NULL; break;
+ }
+ return p;
+}
+
+
+
+static int
+path_absolute_p (const char *p)
+{
+#if _WIN32
+ return ((strlen (p) > 2 && p[1] == ':' && (p[2] == '\\' || p[2] == '/'))
+ || p[0] == '\\' || p[0] == '/');
+#else
+ return p[0] == '/';
+#endif
+}
+
+
+/* Load the Scheme program from FILE_NAME. If FILE_NAME is not an
+ absolute path, and LOOKUP_IN_PATH is given, then it is qualified
+ with the values in scmpath until the file is found. */
+static gpg_error_t
+load (scheme *sc, char *file_name,
+ int lookup_in_cwd, int lookup_in_path)
+{
+ gpg_error_t err = 0;
+ size_t n;
+ const char *directory;
+ char *qualified_name = file_name;
+ int use_path;
+ FILE *h = NULL;
+
+ use_path =
+ lookup_in_path && ! (path_absolute_p (file_name) || scmpath_len == 0);
+
+ if (path_absolute_p (file_name) || lookup_in_cwd || scmpath_len == 0)
+ {
+ h = fopen (file_name, "r");
+ if (! h)
+ err = gpg_error_from_syserror ();
+ }
+
+ if (h == NULL && use_path)
+ for (directory = scmpath, n = scmpath_len; n;
+ directory += strlen (directory) + 1, n--)
+ {
+ if (asprintf (&qualified_name, "%s/%s", directory, file_name) < 0)
+ return gpg_error_from_syserror ();
+
+ h = fopen (qualified_name, "r");
+ if (h)
+ {
+ err = 0;
+ break;
+ }
+
+ if (n > 1)
+ {
+ free (qualified_name);
+ continue; /* Try again! */
+ }
+
+ err = gpg_error_from_syserror ();
+ }
+
+ if (h == NULL)
+ {
+ /* Failed and no more elements in scmpath to try. */
+ fprintf (stderr, "Could not read %s: %s.\n",
+ qualified_name, gpg_strerror (err));
+ if (lookup_in_path)
+ fprintf (stderr,
+ "Consider using GPGSCM_PATH to specify the location "
+ "of the Scheme library.\n");
+ goto leave;
+ }
+ if (verbose > 2)
+ fprintf (stderr, "Loading %s...\n", qualified_name);
+
+#if HAVE_MMAP
+ /* Always try to mmap the file. This allows the pages to be shared
+ * between processes. If anything fails, we fall back to using
+ * buffered streams. */
+ if (1)
+ {
+ struct stat st;
+ void *map;
+ size_t len;
+ int fd = fileno (h);
+
+ if (fd < 0)
+ goto fallback;
+
+ if (fstat (fd, &st))
+ goto fallback;
+
+ len = (size_t) st.st_size;
+ if ((off_t) len != st.st_size)
+ goto fallback; /* Truncated. */
+
+ map = mmap (NULL, len, PROT_READ, MAP_SHARED, fd, 0);
+ if (map == MAP_FAILED)
+ goto fallback;
+
+ scheme_load_memory (sc, map, len, qualified_name);
+ munmap (map, len);
+ }
+ else
+ fallback:
+#endif
+ scheme_load_named_file (sc, h, qualified_name);
+ fclose (h);
+
+ if (sc->retcode && sc->nesting)
+ {
+ fprintf (stderr, "%s: Unbalanced parenthesis\n", qualified_name);
+ err = gpg_error (GPG_ERR_GENERAL);
+ }
+
+ leave:
+ if (file_name != qualified_name)
+ free (qualified_name);
+ return err;
+}
+
+
+
+int
+main (int argc, char **argv)
+{
+ int retcode;
+ gpg_error_t err;
+ char *argv0;
+ ARGPARSE_ARGS pargs;
+ scheme *sc;
+ char *p;
+#if _WIN32
+ char pathsep = ';';
+#else
+ char pathsep = ':';
+#endif
+ char *script = NULL;
+
+ /* Save argv[0] so that we can re-exec. */
+ argv0 = argv[0];
+
+ /* Parse path. */
+ if (getenv ("GPGSCM_PATH"))
+ scmpath = getenv ("GPGSCM_PATH");
+
+ p = scmpath = strdup (scmpath);
+ if (p == NULL)
+ return 2;
+
+ if (*p)
+ scmpath_len++;
+ for (; *p; p++)
+ if (*p == pathsep)
+ *p = 0, scmpath_len++;
+
+ set_strusage (my_strusage);
+ log_set_prefix ("gpgscm", GPGRT_LOG_WITH_PREFIX);
+
+ /* Make sure that our subsystems are ready. */
+ i18n_init ();
+ init_common_subsystems (&argc, &argv);
+
+ if (!gcry_check_version (NEED_LIBGCRYPT_VERSION))
+ {
+ fputs ("libgcrypt version mismatch\n", stderr);
+ exit (2);
+ }
+
+ /* Parse the command line. */
+ pargs.argc = &argc;
+ pargs.argv = &argv;
+ pargs.flags = 0;
+ parse_arguments (&pargs, opts);
+ gnupg_argparse (NULL, &pargs, NULL);
+
+ if (log_get_errorcount (0))
+ exit (2);
+
+ sc = scheme_init_new_custom_alloc (gcry_malloc, gcry_free);
+ if (! sc) {
+ fprintf (stderr, "Could not initialize TinyScheme!\n");
+ return 2;
+ }
+ scheme_set_input_port_file (sc, stdin);
+ scheme_set_output_port_file (sc, stderr);
+
+ if (argc)
+ {
+ script = argv[0];
+ argc--, argv++;
+ }
+
+ err = load (sc, "init.scm", 0, 1);
+ if (! err)
+ err = load (sc, "ffi.scm", 0, 1);
+ if (! err)
+ err = ffi_init (sc, argv0, script ? script : "interactive",
+ argc, (const char **) argv);
+ if (! err)
+ err = load (sc, "lib.scm", 0, 1);
+ if (! err)
+ err = load (sc, "repl.scm", 0, 1);
+ if (! err)
+ err = load (sc, "xml.scm", 0, 1);
+ if (! err)
+ err = load (sc, "tests.scm", 0, 1);
+ if (! err)
+ err = load (sc, "gnupg.scm", 0, 1);
+ if (err)
+ {
+ fprintf (stderr, "Error initializing gpgscm: %s.\n",
+ gpg_strerror (err));
+ exit (2);
+ }
+
+ if (script == NULL)
+ {
+ /* Interactive shell. */
+ fprintf (stderr, "gpgscm/"ts_banner".\n");
+ scheme_load_string (sc, "(interactive-repl)");
+ }
+ else
+ {
+ err = load (sc, script, 1, 1);
+ if (err)
+ log_fatal ("%s: %s", script, gpg_strerror (err));
+ }
+
+ retcode = sc->retcode;
+ scheme_load_string (sc, "(*run-atexit-handlers*)");
+ scheme_deinit (sc);
+ xfree (sc);
+ return retcode;
+}
diff --git a/tests/gpgscm/makefile.scm b/tests/gpgscm/makefile.scm
new file mode 100644
index 0000000..32fae3a
--- /dev/null
+++ b/tests/gpgscm/makefile.scm
@@ -0,0 +1,76 @@
+;; Support for parsing Makefiles
+;;
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(define (parse-makefile port key)
+ (define (is-continuation? tokens)
+ (string=? (last tokens) "\\"))
+ (define (valid-token? s)
+ (< 0 (string-length s)))
+ (define (drop-continuations tokens)
+ (let loop ((acc '()) (tks tokens))
+ (if (null? tks)
+ (reverse acc)
+ (loop (if (string=? "\\" (car tks))
+ acc
+ (cons (car tks) acc)) (cdr tks)))))
+ (let next ((acc '()) (found #f))
+ (let ((line (read-line port)))
+ (if (eof-object? line)
+ acc
+ (let ((tokens (filter valid-token?
+ (string-splitp (string-trim char-whitespace?
+ line)
+ char-whitespace? -1))))
+ (cond
+ ((or (null? tokens)
+ (string-prefix? (car tokens) "#")
+ (and (not found) (not (and (string=? key (car tokens))
+ (string=? "=" (cadr tokens))))))
+ (next acc found))
+ ((not found)
+ (assert (and (string=? key (car tokens))
+ (string=? "=" (cadr tokens))))
+ (if (is-continuation? tokens)
+ (next (drop-continuations (cddr tokens)) #t)
+ (drop-continuations (cddr tokens))))
+ (else
+ (assert found)
+ (if (is-continuation? tokens)
+ (next (append acc (drop-continuations tokens)) found)
+ (append acc (drop-continuations tokens))))))))))
+
+(define (parse-makefile-expand filename expand key)
+ (define (variable? v)
+ (and (string-prefix? v "$(") (string-suffix? v ")")))
+
+ (let expand-all ((values (parse-makefile (open-input-file filename) key)))
+ (if (any variable? values)
+ (expand-all
+ (let expand-one ((acc '()) (v values))
+ (cond
+ ((null? v)
+ acc)
+ ((variable? (car v))
+ (let ((makefile (open-input-file filename))
+ (key (substring (car v) 2 (- (string-length (car v)) 1))))
+ (expand-one (append acc (expand filename makefile key))
+ (cdr v))))
+ (else
+ (expand-one (append acc (list (car v))) (cdr v))))))
+ values)))
diff --git a/tests/gpgscm/opdefines.h b/tests/gpgscm/opdefines.h
new file mode 100644
index 0000000..61f7971
--- /dev/null
+++ b/tests/gpgscm/opdefines.h
@@ -0,0 +1,205 @@
+_OP_DEF("load", 1, 1, TST_STRING, OP_LOAD )
+_OP_DEF(0, 0, 0, 0, OP_T0LVL )
+_OP_DEF(0, 0, 0, 0, OP_T1LVL )
+_OP_DEF(0, 0, 0, 0, OP_READ_INTERNAL )
+_OP_DEF("gensym", 0, 0, 0, OP_GENSYM )
+_OP_DEF(0, 0, 0, 0, OP_VALUEPRINT )
+_OP_DEF(0, 0, 0, 0, OP_EVAL )
+#if USE_TRACING
+_OP_DEF(0, 0, 0, 0, OP_REAL_EVAL )
+#endif
+_OP_DEF(0, 0, 0, 0, OP_E0ARGS )
+_OP_DEF(0, 0, 0, 0, OP_E1ARGS )
+#if USE_HISTORY
+_OP_DEF(0, 0, 0, 0, OP_CALLSTACK_POP )
+#endif
+_OP_DEF(0, 0, 0, 0, OP_APPLY_CODE )
+_OP_DEF(0, 0, 0, 0, OP_APPLY )
+#if USE_TRACING
+_OP_DEF(0, 0, 0, 0, OP_REAL_APPLY )
+_OP_DEF("tracing", 1, 1, TST_NATURAL, OP_TRACING )
+#endif
+_OP_DEF(0, 0, 0, 0, OP_DOMACRO )
+_OP_DEF(0, 0, 0, 0, OP_LAMBDA )
+_OP_DEF(0, 0, 0, 0, OP_LAMBDA1 )
+_OP_DEF("make-closure", 1, 2, TST_PAIR TST_ENVIRONMENT, OP_MKCLOSURE )
+_OP_DEF(0, 0, 0, 0, OP_QUOTE )
+_OP_DEF(0, 0, 0, 0, OP_DEF0 )
+_OP_DEF(0, 0, 0, 0, OP_DEF1 )
+_OP_DEF("defined?", 1, 2, TST_SYMBOL TST_ENVIRONMENT, OP_DEFP )
+_OP_DEF(0, 0, 0, 0, OP_BEGIN )
+_OP_DEF(0, 0, 0, 0, OP_IF0 )
+_OP_DEF(0, 0, 0, 0, OP_IF1 )
+_OP_DEF(0, 0, 0, 0, OP_SET0 )
+_OP_DEF(0, 0, 0, 0, OP_SET1 )
+_OP_DEF(0, 0, 0, 0, OP_LET0 )
+_OP_DEF(0, 0, 0, 0, OP_LET1 )
+_OP_DEF(0, 0, 0, 0, OP_LET2 )
+_OP_DEF(0, 0, 0, 0, OP_LET0AST )
+_OP_DEF(0, 0, 0, 0, OP_LET1AST )
+_OP_DEF(0, 0, 0, 0, OP_LET2AST )
+_OP_DEF(0, 0, 0, 0, OP_LET0REC )
+_OP_DEF(0, 0, 0, 0, OP_LET1REC )
+_OP_DEF(0, 0, 0, 0, OP_LET2REC )
+_OP_DEF(0, 0, 0, 0, OP_COND0 )
+_OP_DEF(0, 0, 0, 0, OP_COND1 )
+_OP_DEF(0, 0, 0, 0, OP_DELAY )
+_OP_DEF(0, 0, 0, 0, OP_AND0 )
+_OP_DEF(0, 0, 0, 0, OP_AND1 )
+_OP_DEF(0, 0, 0, 0, OP_OR0 )
+_OP_DEF(0, 0, 0, 0, OP_OR1 )
+_OP_DEF(0, 0, 0, 0, OP_C0STREAM )
+_OP_DEF(0, 0, 0, 0, OP_C1STREAM )
+_OP_DEF(0, 0, 0, 0, OP_MACRO0 )
+_OP_DEF(0, 0, 0, 0, OP_MACRO1 )
+_OP_DEF(0, 0, 0, 0, OP_CASE0 )
+_OP_DEF(0, 0, 0, 0, OP_CASE1 )
+_OP_DEF(0, 0, 0, 0, OP_CASE2 )
+_OP_DEF("eval", 1, 2, TST_ANY TST_ENVIRONMENT, OP_PEVAL )
+_OP_DEF("apply", 1, INF_ARG, TST_NONE, OP_PAPPLY )
+_OP_DEF("call-with-current-continuation", 1, 1, TST_NONE, OP_CONTINUATION )
+#if USE_MATH
+_OP_DEF("inexact->exact", 1, 1, TST_NUMBER, OP_INEX2EX )
+_OP_DEF("exp", 1, 1, TST_NUMBER, OP_EXP )
+_OP_DEF("log", 1, 1, TST_NUMBER, OP_LOG )
+_OP_DEF("sin", 1, 1, TST_NUMBER, OP_SIN )
+_OP_DEF("cos", 1, 1, TST_NUMBER, OP_COS )
+_OP_DEF("tan", 1, 1, TST_NUMBER, OP_TAN )
+_OP_DEF("asin", 1, 1, TST_NUMBER, OP_ASIN )
+_OP_DEF("acos", 1, 1, TST_NUMBER, OP_ACOS )
+_OP_DEF("atan", 1, 2, TST_NUMBER, OP_ATAN )
+_OP_DEF("sqrt", 1, 1, TST_NUMBER, OP_SQRT )
+_OP_DEF("expt", 2, 2, TST_NUMBER, OP_EXPT )
+_OP_DEF("floor", 1, 1, TST_NUMBER, OP_FLOOR )
+_OP_DEF("ceiling", 1, 1, TST_NUMBER, OP_CEILING )
+_OP_DEF("truncate", 1, 1, TST_NUMBER, OP_TRUNCATE )
+_OP_DEF("round", 1, 1, TST_NUMBER, OP_ROUND )
+#endif
+_OP_DEF("+", 0, INF_ARG, TST_NUMBER, OP_ADD )
+_OP_DEF("-", 1, INF_ARG, TST_NUMBER, OP_SUB )
+_OP_DEF("*", 0, INF_ARG, TST_NUMBER, OP_MUL )
+_OP_DEF("/", 1, INF_ARG, TST_NUMBER, OP_DIV )
+_OP_DEF("quotient", 1, INF_ARG, TST_INTEGER, OP_INTDIV )
+_OP_DEF("remainder", 2, 2, TST_INTEGER, OP_REM )
+_OP_DEF("modulo", 2, 2, TST_INTEGER, OP_MOD )
+_OP_DEF("car", 1, 1, TST_PAIR, OP_CAR )
+_OP_DEF("cdr", 1, 1, TST_PAIR, OP_CDR )
+_OP_DEF("cons", 2, 2, TST_NONE, OP_CONS )
+_OP_DEF("set-car!", 2, 2, TST_PAIR TST_ANY, OP_SETCAR )
+_OP_DEF("set-cdr!", 2, 2, TST_PAIR TST_ANY, OP_SETCDR )
+_OP_DEF("char->integer", 1, 1, TST_CHAR, OP_CHAR2INT )
+_OP_DEF("integer->char", 1, 1, TST_NATURAL, OP_INT2CHAR )
+_OP_DEF("char-upcase", 1, 1, TST_CHAR, OP_CHARUPCASE )
+_OP_DEF("char-downcase", 1, 1, TST_CHAR, OP_CHARDNCASE )
+_OP_DEF("symbol->string", 1, 1, TST_SYMBOL, OP_SYM2STR )
+_OP_DEF("atom->string", 1, 2, TST_ANY TST_NATURAL, OP_ATOM2STR )
+_OP_DEF("string->symbol", 1, 1, TST_STRING, OP_STR2SYM )
+_OP_DEF("string->atom", 1, 2, TST_STRING TST_NATURAL, OP_STR2ATOM )
+_OP_DEF("make-string", 1, 2, TST_NATURAL TST_CHAR, OP_MKSTRING )
+_OP_DEF("string-length", 1, 1, TST_STRING, OP_STRLEN )
+_OP_DEF("string-ref", 2, 2, TST_STRING TST_NATURAL, OP_STRREF )
+_OP_DEF("string-set!", 3, 3, TST_STRING TST_NATURAL TST_CHAR, OP_STRSET )
+_OP_DEF("string-append", 0, INF_ARG, TST_STRING, OP_STRAPPEND )
+_OP_DEF("substring", 2, 3, TST_STRING TST_NATURAL, OP_SUBSTR )
+_OP_DEF("vector", 0, INF_ARG, TST_NONE, OP_VECTOR )
+_OP_DEF("make-vector", 1, 2, TST_NATURAL TST_ANY, OP_MKVECTOR )
+_OP_DEF("vector-length", 1, 1, TST_VECTOR, OP_VECLEN )
+_OP_DEF("vector-ref", 2, 2, TST_VECTOR TST_NATURAL, OP_VECREF )
+_OP_DEF("vector-set!", 3, 3, TST_VECTOR TST_NATURAL TST_ANY, OP_VECSET )
+_OP_DEF("not", 1, 1, TST_NONE, OP_NOT )
+_OP_DEF("boolean?", 1, 1, TST_NONE, OP_BOOLP )
+_OP_DEF("eof-object?", 1, 1, TST_NONE, OP_EOFOBJP )
+_OP_DEF("null?", 1, 1, TST_NONE, OP_NULLP )
+_OP_DEF("=", 2, INF_ARG, TST_NUMBER, OP_NUMEQ )
+_OP_DEF("<", 2, INF_ARG, TST_NUMBER, OP_LESS )
+_OP_DEF(">", 2, INF_ARG, TST_NUMBER, OP_GRE )
+_OP_DEF("<=", 2, INF_ARG, TST_NUMBER, OP_LEQ )
+_OP_DEF(">=", 2, INF_ARG, TST_NUMBER, OP_GEQ )
+_OP_DEF("symbol?", 1, 1, TST_ANY, OP_SYMBOLP )
+_OP_DEF("number?", 1, 1, TST_ANY, OP_NUMBERP )
+_OP_DEF("string?", 1, 1, TST_ANY, OP_STRINGP )
+_OP_DEF("integer?", 1, 1, TST_ANY, OP_INTEGERP )
+_OP_DEF("real?", 1, 1, TST_ANY, OP_REALP )
+_OP_DEF("char?", 1, 1, TST_ANY, OP_CHARP )
+#if USE_CHAR_CLASSIFIERS
+_OP_DEF("char-alphabetic?", 1, 1, TST_CHAR, OP_CHARAP )
+_OP_DEF("char-numeric?", 1, 1, TST_CHAR, OP_CHARNP )
+_OP_DEF("char-whitespace?", 1, 1, TST_CHAR, OP_CHARWP )
+_OP_DEF("char-upper-case?", 1, 1, TST_CHAR, OP_CHARUP )
+_OP_DEF("char-lower-case?", 1, 1, TST_CHAR, OP_CHARLP )
+#endif
+_OP_DEF("port?", 1, 1, TST_ANY, OP_PORTP )
+_OP_DEF("input-port?", 1, 1, TST_ANY, OP_INPORTP )
+_OP_DEF("output-port?", 1, 1, TST_ANY, OP_OUTPORTP )
+_OP_DEF("procedure?", 1, 1, TST_ANY, OP_PROCP )
+_OP_DEF("pair?", 1, 1, TST_ANY, OP_PAIRP )
+_OP_DEF("list?", 1, 1, TST_ANY, OP_LISTP )
+_OP_DEF("environment?", 1, 1, TST_ANY, OP_ENVP )
+_OP_DEF("vector?", 1, 1, TST_ANY, OP_VECTORP )
+_OP_DEF("eq?", 2, 2, TST_ANY, OP_EQ )
+_OP_DEF("eqv?", 2, 2, TST_ANY, OP_EQV )
+_OP_DEF("force", 1, 1, TST_ANY, OP_FORCE )
+_OP_DEF(0, 0, 0, 0, OP_SAVE_FORCED )
+_OP_DEF("write", 1, 2, TST_ANY TST_OUTPORT, OP_WRITE )
+_OP_DEF("write-char", 1, 2, TST_CHAR TST_OUTPORT, OP_WRITE_CHAR )
+_OP_DEF("display", 1, 2, TST_ANY TST_OUTPORT, OP_DISPLAY )
+_OP_DEF("newline", 0, 1, TST_OUTPORT, OP_NEWLINE )
+_OP_DEF("error", 1, INF_ARG, TST_NONE, OP_ERR0 )
+_OP_DEF(0, 0, 0, 0, OP_ERR1 )
+_OP_DEF("reverse", 1, 1, TST_LIST, OP_REVERSE )
+_OP_DEF("reverse!", 1, 1, TST_LIST, OP_REVERSE_IN_PLACE )
+_OP_DEF("list*", 1, INF_ARG, TST_NONE, OP_LIST_STAR )
+_OP_DEF("append", 0, INF_ARG, TST_NONE, OP_APPEND )
+#if USE_PLIST
+_OP_DEF("set-symbol-property!", 3, 3, TST_SYMBOL TST_SYMBOL TST_ANY, OP_SET_SYMBOL_PROPERTY )
+_OP_DEF("symbol-property", 2, 2, TST_SYMBOL TST_SYMBOL, OP_SYMBOL_PROPERTY )
+#endif
+_OP_DEF(0, 0, 0, TST_NONE, OP_TAG_VALUE )
+_OP_DEF("make-tagged-value", 2, 2, TST_ANY TST_PAIR, OP_MK_TAGGED )
+_OP_DEF("get-tag", 1, 1, TST_ANY, OP_GET_TAG )
+_OP_DEF("quit", 0, 1, TST_NUMBER, OP_QUIT )
+_OP_DEF("gc", 0, 0, 0, OP_GC )
+_OP_DEF("gc-verbose", 0, 1, TST_NONE, OP_GCVERB )
+_OP_DEF("new-segment", 0, 1, TST_NUMBER, OP_NEWSEGMENT )
+_OP_DEF("oblist", 0, 0, 0, OP_OBLIST )
+_OP_DEF("current-input-port", 0, 0, 0, OP_CURR_INPORT )
+_OP_DEF("current-output-port", 0, 0, 0, OP_CURR_OUTPORT )
+_OP_DEF("open-input-file", 1, 1, TST_STRING, OP_OPEN_INFILE )
+_OP_DEF("open-output-file", 1, 1, TST_STRING, OP_OPEN_OUTFILE )
+_OP_DEF("open-input-output-file", 1, 1, TST_STRING, OP_OPEN_INOUTFILE )
+#if USE_STRING_PORTS
+_OP_DEF("open-input-string", 1, 1, TST_STRING, OP_OPEN_INSTRING )
+_OP_DEF("open-input-output-string", 1, 1, TST_STRING, OP_OPEN_INOUTSTRING )
+_OP_DEF("open-output-string", 0, 1, TST_STRING, OP_OPEN_OUTSTRING )
+_OP_DEF("get-output-string", 1, 1, TST_OUTPORT, OP_GET_OUTSTRING )
+#endif
+_OP_DEF("close-input-port", 1, 1, TST_INPORT, OP_CLOSE_INPORT )
+_OP_DEF("close-output-port", 1, 1, TST_OUTPORT, OP_CLOSE_OUTPORT )
+_OP_DEF("interaction-environment", 0, 0, 0, OP_INT_ENV )
+_OP_DEF("current-environment", 0, 0, 0, OP_CURR_ENV )
+_OP_DEF("read", 0, 1, TST_INPORT, OP_READ )
+_OP_DEF("read-char", 0, 1, TST_INPORT, OP_READ_CHAR )
+_OP_DEF("peek-char", 0, 1, TST_INPORT, OP_PEEK_CHAR )
+_OP_DEF("char-ready?", 0, 1, TST_INPORT, OP_CHAR_READY )
+_OP_DEF("set-input-port", 1, 1, TST_INPORT, OP_SET_INPORT )
+_OP_DEF("set-output-port", 1, 1, TST_OUTPORT, OP_SET_OUTPORT )
+_OP_DEF(0, 0, 0, 0, OP_RDSEXPR )
+_OP_DEF(0, 0, 0, 0, OP_RDLIST )
+_OP_DEF(0, 0, 0, 0, OP_RDDOT )
+_OP_DEF(0, 0, 0, 0, OP_RDQUOTE )
+_OP_DEF(0, 0, 0, 0, OP_RDQQUOTE )
+_OP_DEF(0, 0, 0, 0, OP_RDQQUOTEVEC )
+_OP_DEF(0, 0, 0, 0, OP_RDUNQUOTE )
+_OP_DEF(0, 0, 0, 0, OP_RDUQTSP )
+_OP_DEF(0, 0, 0, 0, OP_RDVEC )
+_OP_DEF(0, 0, 0, 0, OP_P0LIST )
+_OP_DEF(0, 0, 0, 0, OP_P1LIST )
+_OP_DEF(0, 0, 0, 0, OP_PVECFROM )
+_OP_DEF("length", 1, 1, TST_LIST, OP_LIST_LENGTH )
+_OP_DEF("assq", 2, 2, TST_NONE, OP_ASSQ )
+_OP_DEF("get-closure-code", 1, 1, TST_NONE, OP_GET_CLOSURE )
+_OP_DEF("closure?", 1, 1, TST_NONE, OP_CLOSUREP )
+_OP_DEF("macro?", 1, 1, TST_NONE, OP_MACROP )
+_OP_DEF("*vm-history*", 0, 0, TST_NONE, OP_VM_HISTORY )
+
+#undef _OP_DEF
diff --git a/tests/gpgscm/private.h b/tests/gpgscm/private.h
new file mode 100644
index 0000000..6e330e0
--- /dev/null
+++ b/tests/gpgscm/private.h
@@ -0,0 +1,26 @@
+/* TinyScheme-based test driver.
+ *
+ * Copyright (C) 2016 g10 code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GPGSCM_PRIVATE_H__
+#define __GPGSCM_PRIVATE_H__
+
+extern int verbose;
+
+#endif /* __GPGSCM_PRIVATE_H__ */
diff --git a/tests/gpgscm/repl.scm b/tests/gpgscm/repl.scm
new file mode 100644
index 0000000..833ec0d
--- /dev/null
+++ b/tests/gpgscm/repl.scm
@@ -0,0 +1,69 @@
+;; A read-evaluate-print-loop for gpgscm.
+;;
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+;; Interactive repl using 'prompt' function. P must be a function
+;; that given the current entered prefix returns the prompt to
+;; display.
+(define (repl p environment)
+ (call/cc
+ (lambda (exit)
+ (let loop ((prefix ""))
+ (let ((line (prompt (p prefix))))
+ (if (and (not (eof-object? line)) (= 0 (string-length line)))
+ (exit (loop prefix)))
+ (if (not (eof-object? line))
+ (let* ((next (string-append prefix line))
+ (c (catch (begin (echo "Parse error:" *error*)
+ (loop prefix))
+ (read (open-input-string next)))))
+ (if (not (eof-object? c))
+ (begin
+ (catch (begin
+ (display (car *error*))
+ (when (and (cadr *error*)
+ (not (null? (cadr *error*))))
+ (display ": ")
+ (write (cadr *error*)))
+ (newline)
+ (vm-history-print (caddr *error*)))
+ (echo " ===>" (eval c environment)))
+ (exit (loop ""))))
+ (exit (loop next)))))))))
+
+(define (prompt-append-prefix prompt prefix)
+ (string-append prompt (if (> (string-length prefix) 0)
+ (string-append prefix "...")
+ "> ")))
+
+;; Default repl run by main.c.
+(define (interactive-repl . environment)
+ (repl (lambda (p) (prompt-append-prefix "gpgscm " p))
+ (if (null? environment) (interaction-environment) (car environment))))
+
+;; Ask a yes/no question.
+(define (prompt-yes-no? question default)
+ (let ((answer (prompt (string-append question "? ["
+ (if default "Y/n" "y/N") "] "))))
+ (cond
+ ((= 0 (string-length answer))
+ default)
+ ((or (equal? "y" answer) (equal? "Y" answer))
+ #t)
+ (else
+ #f))))
diff --git a/tests/gpgscm/scheme-config.h b/tests/gpgscm/scheme-config.h
new file mode 100644
index 0000000..15ca969
--- /dev/null
+++ b/tests/gpgscm/scheme-config.h
@@ -0,0 +1,32 @@
+/* TinyScheme configuration.
+ *
+ * Copyright (C) 2016 g10 code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#define STANDALONE 0
+#define USE_MATH 0
+#define USE_CHAR_CLASSIFIERS 1
+#define USE_ASCII_NAMES 1
+#define USE_STRING_PORTS 1
+#define USE_ERROR_HOOK 1
+#define USE_TRACING 1
+#define USE_COLON_HOOK 1
+#define USE_DL 0
+#define USE_PLIST 0
+#define USE_INTERFACE 1
+#define SHOW_ERROR_LINE 1
diff --git a/tests/gpgscm/scheme-private.h b/tests/gpgscm/scheme-private.h
new file mode 100644
index 0000000..7f92bda
--- /dev/null
+++ b/tests/gpgscm/scheme-private.h
@@ -0,0 +1,274 @@
+/* scheme-private.h */
+
+#ifndef _SCHEME_PRIVATE_H
+#define _SCHEME_PRIVATE_H
+
+#include <stdint.h>
+#include "scheme.h"
+/*------------------ Ugly internals -----------------------------------*/
+/*------------------ Of interest only to FFI users --------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum scheme_port_kind {
+ port_free=0,
+ port_file=1,
+ port_string=2,
+ port_srfi6=4,
+ port_input=16,
+ port_output=32,
+ port_saw_EOF=64
+};
+
+typedef struct port {
+ unsigned char kind;
+ union {
+ struct {
+ FILE *file;
+ int closeit;
+ } stdio;
+ struct {
+ char *start;
+ char *past_the_end;
+ char *curr;
+ } string;
+ } rep;
+#if SHOW_ERROR_LINE
+ pointer curr_line;
+ pointer filename;
+#endif
+} port;
+
+/* cell structure */
+struct cell {
+ uintptr_t _flag;
+ union {
+ num _number;
+ struct {
+ char *_svalue;
+ int _length;
+ } _string;
+ port *_port;
+ foreign_func _ff;
+ struct {
+ struct cell *_car;
+ struct cell *_cdr;
+ } _cons;
+ struct {
+ size_t _length;
+ pointer _elements[0];
+ } _vector;
+ struct {
+ char *_data;
+ const foreign_object_vtable *_vtable;
+ } _foreign_object;
+ } _object;
+};
+
+#if USE_HISTORY
+/* The history is a two-dimensional ring buffer. A donut-shaped data
+ * structure. This data structure is inspired by MIT/GNU Scheme. */
+struct history {
+ /* Number of calls to store. Must be a power of two. */
+ size_t N;
+
+ /* Number of tail-calls to store in each call frame. Must be a
+ * power of two. */
+ size_t M;
+
+ /* Masks for fast index calculations. */
+ size_t mask_N;
+ size_t mask_M;
+
+ /* A vector of size N containing calls. */
+ pointer callstack;
+
+ /* A vector of size N containing vectors of size M containing tail
+ * calls. */
+ pointer tailstacks;
+
+ /* Our current position. */
+ size_t n;
+ size_t *m;
+};
+#endif
+
+struct scheme {
+/* arrays for segments */
+func_alloc malloc;
+func_dealloc free;
+
+/* return code */
+int retcode;
+int tracing;
+
+
+#ifndef CELL_SEGSIZE
+#define CELL_SEGSIZE 5000 /* # of cells in one segment */
+#endif
+
+/* If less than # of cells are recovered in a garbage collector run,
+ * allocate a new cell segment to avoid fruitless collection cycles in
+ * the near future. */
+#ifndef CELL_MINRECOVER
+#define CELL_MINRECOVER (CELL_SEGSIZE >> 2)
+#endif
+struct cell_segment *cell_segments;
+
+/* We use 4 registers. */
+pointer args; /* register for arguments of function */
+pointer envir; /* stack register for current environment */
+pointer code; /* register for current code */
+pointer dump; /* stack register for next evaluation */
+pointer frame_freelist;
+
+#if USE_HISTORY
+struct history history; /* we keep track of the call history for
+ * error messages */
+#endif
+
+int interactive_repl; /* are we in an interactive REPL? */
+
+struct cell _sink;
+pointer sink; /* when mem. alloc. fails */
+struct cell _NIL;
+pointer NIL; /* special cell representing empty cell */
+struct cell _HASHT;
+pointer T; /* special cell representing #t */
+struct cell _HASHF;
+pointer F; /* special cell representing #f */
+struct cell _EOF_OBJ;
+pointer EOF_OBJ; /* special cell representing end-of-file object */
+pointer oblist; /* pointer to symbol table */
+pointer global_env; /* pointer to global environment */
+pointer c_nest; /* stack for nested calls from C */
+
+/* global pointers to special symbols */
+pointer LAMBDA; /* pointer to syntax lambda */
+pointer QUOTE; /* pointer to syntax quote */
+
+pointer QQUOTE; /* pointer to symbol quasiquote */
+pointer UNQUOTE; /* pointer to symbol unquote */
+pointer UNQUOTESP; /* pointer to symbol unquote-splicing */
+pointer FEED_TO; /* => */
+pointer COLON_HOOK; /* *colon-hook* */
+pointer ERROR_HOOK; /* *error-hook* */
+pointer SHARP_HOOK; /* *sharp-hook* */
+#if USE_COMPILE_HOOK
+pointer COMPILE_HOOK; /* *compile-hook* */
+#endif
+
+pointer free_cell; /* pointer to top of free cells */
+long fcells; /* # of free cells */
+size_t inhibit_gc; /* nesting of gc_disable */
+size_t reserved_cells; /* # of reserved cells */
+#ifndef NDEBUG
+int reserved_lineno; /* location of last reservation */
+#endif
+
+pointer inport;
+pointer outport;
+pointer save_inport;
+pointer loadport;
+
+#ifndef MAXFIL
+#define MAXFIL 64
+#endif
+port load_stack[MAXFIL]; /* Stack of open files for port -1 (LOADing) */
+int nesting_stack[MAXFIL];
+int file_i;
+int nesting;
+
+char gc_verbose; /* if gc_verbose is not zero, print gc status */
+char no_memory; /* Whether mem. alloc. has failed */
+
+#ifndef LINESIZE
+#define LINESIZE 1024
+#endif
+char linebuff[LINESIZE];
+#ifndef STRBUFFSIZE
+#define STRBUFFSIZE 256
+#endif
+char *strbuff;
+size_t strbuff_size;
+FILE *tmpfp;
+int tok;
+int print_flag;
+pointer value;
+unsigned int flags;
+
+void *ext_data; /* For the benefit of foreign functions */
+long gensym_cnt;
+
+const struct scheme_interface *vptr;
+};
+
+/* operator code */
+enum scheme_opcodes {
+#define _OP_DEF(A,B,C,D,OP) OP,
+#include "opdefines.h"
+ OP_MAXDEFINED
+};
+
+
+#define cons(sc,a,b) _cons(sc,a,b,0)
+#define immutable_cons(sc,a,b) _cons(sc,a,b,1)
+
+int is_string(pointer p);
+char *string_value(pointer p);
+int is_number(pointer p);
+num nvalue(pointer p);
+long ivalue(pointer p);
+double rvalue(pointer p);
+int is_integer(pointer p);
+int is_real(pointer p);
+int is_character(pointer p);
+long charvalue(pointer p);
+int is_vector(pointer p);
+
+int is_port(pointer p);
+
+int is_pair(pointer p);
+pointer pair_car(pointer p);
+pointer pair_cdr(pointer p);
+pointer set_car(pointer p, pointer q);
+pointer set_cdr(pointer p, pointer q);
+
+int is_symbol(pointer p);
+char *symname(pointer p);
+int hasprop(pointer p);
+
+int is_syntax(pointer p);
+int is_proc(pointer p);
+int is_foreign(pointer p);
+char *syntaxname(pointer p);
+int is_closure(pointer p);
+#ifdef USE_MACRO
+int is_macro(pointer p);
+#endif
+pointer closure_code(pointer p);
+pointer closure_env(pointer p);
+
+int is_continuation(pointer p);
+int is_promise(pointer p);
+int is_environment(pointer p);
+int is_immutable(pointer p);
+void setimmutable(pointer p);
+
+int is_foreign_object(pointer p);
+const foreign_object_vtable *get_foreign_object_vtable(pointer p);
+void *get_foreign_object_data(pointer p);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/*
+Local variables:
+c-file-style: "k&r"
+End:
+*/
diff --git a/tests/gpgscm/scheme.c b/tests/gpgscm/scheme.c
new file mode 100644
index 0000000..86d70b3
--- /dev/null
+++ b/tests/gpgscm/scheme.c
@@ -0,0 +1,6043 @@
+/* T I N Y S C H E M E 1 . 4 1
+ * Dimitrios Souflis (dsouflis@acm.org)
+ * Based on MiniScheme (original credits follow)
+ * (MINISCM) coded by Atsushi Moriwaki (11/5/1989)
+ * (MINISCM) E-MAIL : moriwaki@kurims.kurims.kyoto-u.ac.jp
+ * (MINISCM) This version has been modified by R.C. Secrist.
+ * (MINISCM)
+ * (MINISCM) Mini-Scheme is now maintained by Akira KIDA.
+ * (MINISCM)
+ * (MINISCM) This is a revised and modified version by Akira KIDA.
+ * (MINISCM) current version is 0.85k4 (15 May 1994)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define _SCHEME_SOURCE
+#include "scheme-private.h"
+#ifndef WIN32
+# include <unistd.h>
+#endif
+#ifdef WIN32
+#define snprintf _snprintf
+#endif
+#if USE_DL
+# include "dynload.h"
+#endif
+#if USE_MATH
+# include <math.h>
+#endif
+
+#include <assert.h>
+#include <limits.h>
+#include <stdint.h>
+#include <float.h>
+#include <ctype.h>
+
+#if USE_STRCASECMP
+#include <strings.h>
+# ifndef __APPLE__
+# define stricmp strcasecmp
+# endif
+#endif
+
+#include "gpgrt.h" /* For GGPRT_GCC_VERSION */
+
+/* Used for documentation purposes, to signal functions in 'interface' */
+#define INTERFACE
+
+#define TOK_EOF (-1)
+#define TOK_LPAREN 0
+#define TOK_RPAREN 1
+#define TOK_DOT 2
+#define TOK_ATOM 3
+#define TOK_QUOTE 4
+#define TOK_COMMENT 5
+#define TOK_DQUOTE 6
+#define TOK_BQUOTE 7
+#define TOK_COMMA 8
+#define TOK_ATMARK 9
+#define TOK_SHARP 10
+#define TOK_SHARP_CONST 11
+#define TOK_VEC 12
+
+#define BACKQUOTE '`'
+#define DELIMITERS "()\";\f\t\v\n\r "
+
+/*
+ * Basic memory allocation units
+ */
+
+#define banner "TinyScheme 1.41"
+
+#include <string.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#ifdef __APPLE__
+static int stricmp(const char *s1, const char *s2)
+{
+ unsigned char c1, c2;
+ do {
+ c1 = tolower(*s1);
+ c2 = tolower(*s2);
+ if (c1 < c2)
+ return -1;
+ else if (c1 > c2)
+ return 1;
+ s1++, s2++;
+ } while (c1 != 0);
+ return 0;
+}
+#endif /* __APPLE__ */
+
+#if USE_STRLWR && !defined(HAVE_STRLWR)
+static const char *strlwr(char *s) {
+ const char *p=s;
+ while(*s) {
+ *s=tolower(*s);
+ s++;
+ }
+ return p;
+}
+#endif
+
+#ifndef prompt
+# define prompt "ts> "
+#endif
+
+#ifndef InitFile
+# define InitFile "init.scm"
+#endif
+
+#ifndef FIRST_CELLSEGS
+# define FIRST_CELLSEGS 3
+#endif
+
+
+
+/* All types have the LSB set. The garbage collector takes advantage
+ * of that to identify types. */
+enum scheme_types {
+ T_STRING = 1 << 1 | 1,
+ T_NUMBER = 2 << 1 | 1,
+ T_SYMBOL = 3 << 1 | 1,
+ T_PROC = 4 << 1 | 1,
+ T_PAIR = 5 << 1 | 1,
+ T_CLOSURE = 6 << 1 | 1,
+ T_CONTINUATION = 7 << 1 | 1,
+ T_FOREIGN = 8 << 1 | 1,
+ T_CHARACTER = 9 << 1 | 1,
+ T_PORT = 10 << 1 | 1,
+ T_VECTOR = 11 << 1 | 1,
+ T_MACRO = 12 << 1 | 1,
+ T_PROMISE = 13 << 1 | 1,
+ T_ENVIRONMENT = 14 << 1 | 1,
+ T_FOREIGN_OBJECT = 15 << 1 | 1,
+ T_BOOLEAN = 16 << 1 | 1,
+ T_NIL = 17 << 1 | 1,
+ T_EOF_OBJ = 18 << 1 | 1,
+ T_SINK = 19 << 1 | 1,
+ T_FRAME = 20 << 1 | 1,
+ T_LAST_SYSTEM_TYPE = 20 << 1 | 1
+};
+
+static const char *
+type_to_string (enum scheme_types typ)
+{
+ switch (typ)
+ {
+ case T_STRING: return "string";
+ case T_NUMBER: return "number";
+ case T_SYMBOL: return "symbol";
+ case T_PROC: return "proc";
+ case T_PAIR: return "pair";
+ case T_CLOSURE: return "closure";
+ case T_CONTINUATION: return "continuation";
+ case T_FOREIGN: return "foreign";
+ case T_CHARACTER: return "character";
+ case T_PORT: return "port";
+ case T_VECTOR: return "vector";
+ case T_MACRO: return "macro";
+ case T_PROMISE: return "promise";
+ case T_ENVIRONMENT: return "environment";
+ case T_FOREIGN_OBJECT: return "foreign object";
+ case T_BOOLEAN: return "boolean";
+ case T_NIL: return "nil";
+ case T_EOF_OBJ: return "eof object";
+ case T_SINK: return "sink";
+ case T_FRAME: return "frame";
+ }
+ assert (! "not reached");
+ return "?";
+}
+
+/* ADJ is enough slack to align cells in a TYPE_BITS-bit boundary */
+#define TYPE_BITS 6
+#define ADJ (1 << TYPE_BITS)
+#define T_MASKTYPE (ADJ - 1)
+ /* 0000000000111111 */
+#define T_TAGGED 1024 /* 0000010000000000 */
+#define T_FINALIZE 2048 /* 0000100000000000 */
+#define T_SYNTAX 4096 /* 0001000000000000 */
+#define T_IMMUTABLE 8192 /* 0010000000000000 */
+#define T_ATOM 16384 /* 0100000000000000 */ /* only for gc */
+#define CLRATOM 49151 /* 1011111111111111 */ /* only for gc */
+#define MARK 32768 /* 1000000000000000 */
+#define UNMARK 32767 /* 0111111111111111 */
+
+
+static num num_add(num a, num b);
+static num num_mul(num a, num b);
+static num num_div(num a, num b);
+static num num_intdiv(num a, num b);
+static num num_sub(num a, num b);
+static num num_rem(num a, num b);
+static num num_mod(num a, num b);
+static int num_eq(num a, num b);
+static int num_gt(num a, num b);
+static int num_ge(num a, num b);
+static int num_lt(num a, num b);
+static int num_le(num a, num b);
+
+#if USE_MATH
+static double round_per_R5RS(double x);
+#endif
+static int is_zero_double(double x);
+static INLINE int num_is_integer(pointer p) {
+ return ((p)->_object._number.is_fixnum);
+}
+
+static const struct num num_zero = { 1, {0} };
+static const struct num num_one = { 1, {1} };
+
+/* macros for cell operations */
+#define typeflag(p) ((p)->_flag)
+#define type(p) (typeflag(p)&T_MASKTYPE)
+#define settype(p, typ) (typeflag(p) = (typeflag(p) & ~T_MASKTYPE) | (typ))
+
+INTERFACE INLINE int is_string(pointer p) { return (type(p)==T_STRING); }
+#define strvalue(p) ((p)->_object._string._svalue)
+#define strlength(p) ((p)->_object._string._length)
+
+INTERFACE static int is_list(scheme *sc, pointer p);
+INTERFACE INLINE int is_vector(pointer p) { return (type(p)==T_VECTOR); }
+/* Given a vector, return it's length. */
+#define vector_length(v) (v)->_object._vector._length
+/* Given a vector length, compute the amount of cells required to
+ * represent it. */
+#define vector_size(len) (1 + ((len) - 1 + 2) / 3)
+INTERFACE static void fill_vector(pointer vec, pointer obj);
+INTERFACE static pointer *vector_elem_slot(pointer vec, int ielem);
+INTERFACE static pointer vector_elem(pointer vec, int ielem);
+INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a);
+INTERFACE INLINE int is_number(pointer p) { return (type(p)==T_NUMBER); }
+INTERFACE INLINE int is_integer(pointer p) {
+ if (!is_number(p))
+ return 0;
+ if (num_is_integer(p) || (double)ivalue(p) == rvalue(p))
+ return 1;
+ return 0;
+}
+
+INTERFACE INLINE int is_real(pointer p) {
+ return is_number(p) && (!(p)->_object._number.is_fixnum);
+}
+
+INTERFACE INLINE int is_character(pointer p) { return (type(p)==T_CHARACTER); }
+INTERFACE INLINE char *string_value(pointer p) { return strvalue(p); }
+INLINE num nvalue(pointer p) { return ((p)->_object._number); }
+INTERFACE long ivalue(pointer p) { return (num_is_integer(p)?(p)->_object._number.value.ivalue:(long)(p)->_object._number.value.rvalue); }
+INTERFACE double rvalue(pointer p) { return (!num_is_integer(p)?(p)->_object._number.value.rvalue:(double)(p)->_object._number.value.ivalue); }
+#define ivalue_unchecked(p) ((p)->_object._number.value.ivalue)
+#define rvalue_unchecked(p) ((p)->_object._number.value.rvalue)
+#define set_num_integer(p) (p)->_object._number.is_fixnum=1;
+#define set_num_real(p) (p)->_object._number.is_fixnum=0;
+INTERFACE long charvalue(pointer p) { return ivalue_unchecked(p); }
+
+INTERFACE INLINE int is_port(pointer p) { return (type(p)==T_PORT); }
+INTERFACE INLINE int is_inport(pointer p) { return is_port(p) && p->_object._port->kind & port_input; }
+INTERFACE INLINE int is_outport(pointer p) { return is_port(p) && p->_object._port->kind & port_output; }
+
+INTERFACE INLINE int is_pair(pointer p) { return (type(p)==T_PAIR); }
+#define car(p) ((p)->_object._cons._car)
+#define cdr(p) ((p)->_object._cons._cdr)
+INTERFACE pointer pair_car(pointer p) { return car(p); }
+INTERFACE pointer pair_cdr(pointer p) { return cdr(p); }
+INTERFACE pointer set_car(pointer p, pointer q) { return car(p)=q; }
+INTERFACE pointer set_cdr(pointer p, pointer q) { return cdr(p)=q; }
+
+INTERFACE INLINE int is_symbol(pointer p) { return (type(p)==T_SYMBOL); }
+INTERFACE INLINE char *symname(pointer p) { return strvalue(car(p)); }
+#if USE_PLIST
+SCHEME_EXPORT INLINE int hasprop(pointer p) { return (is_symbol(p)); }
+#define symprop(p) cdr(p)
+#endif
+
+INTERFACE INLINE int is_syntax(pointer p) { return (typeflag(p)&T_SYNTAX); }
+INTERFACE INLINE int is_proc(pointer p) { return (type(p)==T_PROC); }
+INTERFACE INLINE int is_foreign(pointer p) { return (type(p)==T_FOREIGN); }
+INTERFACE INLINE char *syntaxname(pointer p) { return strvalue(car(p)); }
+#define procnum(p) ivalue_unchecked(p)
+static const char *procname(pointer x);
+
+INTERFACE INLINE int is_closure(pointer p) { return (type(p)==T_CLOSURE); }
+INTERFACE INLINE int is_macro(pointer p) { return (type(p)==T_MACRO); }
+INTERFACE INLINE pointer closure_code(pointer p) { return car(p); }
+INTERFACE INLINE pointer closure_env(pointer p) { return cdr(p); }
+
+INTERFACE INLINE int is_continuation(pointer p) { return (type(p)==T_CONTINUATION); }
+#define cont_dump(p) cdr(p)
+
+INTERFACE INLINE int is_foreign_object(pointer p) { return (type(p)==T_FOREIGN_OBJECT); }
+INTERFACE const foreign_object_vtable *get_foreign_object_vtable(pointer p) {
+ return p->_object._foreign_object._vtable;
+}
+INTERFACE void *get_foreign_object_data(pointer p) {
+ return p->_object._foreign_object._data;
+}
+
+/* To do: promise should be forced ONCE only */
+INTERFACE INLINE int is_promise(pointer p) { return (type(p)==T_PROMISE); }
+
+INTERFACE INLINE int is_environment(pointer p) { return (type(p)==T_ENVIRONMENT); }
+#define setenvironment(p) typeflag(p) = T_ENVIRONMENT
+
+INTERFACE INLINE int is_frame(pointer p) { return (type(p) == T_FRAME); }
+#define setframe(p) settype(p, T_FRAME)
+
+#define is_atom(p) (typeflag(p)&T_ATOM)
+#define setatom(p) typeflag(p) |= T_ATOM
+#define clratom(p) typeflag(p) &= CLRATOM
+
+#define is_mark(p) (typeflag(p)&MARK)
+#define setmark(p) typeflag(p) |= MARK
+#define clrmark(p) typeflag(p) &= UNMARK
+
+INTERFACE INLINE int is_immutable(pointer p) { return (typeflag(p)&T_IMMUTABLE); }
+/*#define setimmutable(p) typeflag(p) |= T_IMMUTABLE*/
+INTERFACE INLINE void setimmutable(pointer p) { typeflag(p) |= T_IMMUTABLE; }
+
+#define caar(p) car(car(p))
+#define cadr(p) car(cdr(p))
+#define cdar(p) cdr(car(p))
+#define cddr(p) cdr(cdr(p))
+#define cadar(p) car(cdr(car(p)))
+#define caddr(p) car(cdr(cdr(p)))
+#define cdaar(p) cdr(car(car(p)))
+#define cadaar(p) car(cdr(car(car(p))))
+#define cadddr(p) car(cdr(cdr(cdr(p))))
+#define cddddr(p) cdr(cdr(cdr(cdr(p))))
+
+#if USE_HISTORY
+static pointer history_flatten(scheme *sc);
+static void history_mark(scheme *sc);
+#else
+# define history_mark(SC) (void) 0
+# define history_flatten(SC) (SC)->NIL
+#endif
+
+#if USE_CHAR_CLASSIFIERS
+static INLINE int Cisalpha(int c) { return isascii(c) && isalpha(c); }
+static INLINE int Cisdigit(int c) { return isascii(c) && isdigit(c); }
+static INLINE int Cisspace(int c) { return isascii(c) && isspace(c); }
+static INLINE int Cisupper(int c) { return isascii(c) && isupper(c); }
+static INLINE int Cislower(int c) { return isascii(c) && islower(c); }
+#endif
+
+#if USE_ASCII_NAMES
+static const char charnames[32][3]={
+ "nul",
+ "soh",
+ "stx",
+ "etx",
+ "eot",
+ "enq",
+ "ack",
+ "bel",
+ "bs",
+ "ht",
+ "lf",
+ "vt",
+ "ff",
+ "cr",
+ "so",
+ "si",
+ "dle",
+ "dc1",
+ "dc2",
+ "dc3",
+ "dc4",
+ "nak",
+ "syn",
+ "etb",
+ "can",
+ "em",
+ "sub",
+ "esc",
+ "fs",
+ "gs",
+ "rs",
+ "us"
+};
+
+static int is_ascii_name(const char *name, int *pc) {
+ int i;
+ for(i=0; i<32; i++) {
+ if (strncasecmp(name, charnames[i], 3) == 0) {
+ *pc=i;
+ return 1;
+ }
+ }
+ if (strcasecmp(name, "del") == 0) {
+ *pc=127;
+ return 1;
+ }
+ return 0;
+}
+
+#endif
+
+static int file_push(scheme *sc, pointer fname);
+static void file_pop(scheme *sc);
+static int file_interactive(scheme *sc);
+static INLINE int is_one_of(char *s, int c);
+static int alloc_cellseg(scheme *sc, int n);
+static long binary_decode(const char *s);
+static INLINE pointer get_cell(scheme *sc, pointer a, pointer b);
+static pointer _get_cell(scheme *sc, pointer a, pointer b);
+static pointer reserve_cells(scheme *sc, int n);
+static pointer get_consecutive_cells(scheme *sc, int n);
+static pointer find_consecutive_cells(scheme *sc, int n);
+static int finalize_cell(scheme *sc, pointer a);
+static int count_consecutive_cells(pointer x, int needed);
+static pointer find_slot_in_env(scheme *sc, pointer env, pointer sym, int all);
+static pointer mk_number(scheme *sc, num n);
+static char *store_string(scheme *sc, int len, const char *str, char fill);
+static pointer mk_vector(scheme *sc, int len);
+static pointer mk_atom(scheme *sc, char *q);
+static pointer mk_sharp_const(scheme *sc, char *name);
+static pointer mk_port(scheme *sc, port *p);
+static pointer port_from_filename(scheme *sc, const char *fn, int prop);
+static pointer port_from_file(scheme *sc, FILE *, int prop);
+static pointer port_from_string(scheme *sc, char *start, char *past_the_end, int prop);
+static port *port_rep_from_filename(scheme *sc, const char *fn, int prop);
+static port *port_rep_from_file(scheme *sc, FILE *, int prop);
+static port *port_rep_from_string(scheme *sc, char *start, char *past_the_end, int prop);
+static void port_close(scheme *sc, pointer p, int flag);
+static void mark(pointer a);
+static void gc(scheme *sc, pointer a, pointer b);
+static int basic_inchar(port *pt);
+static int inchar(scheme *sc);
+static void backchar(scheme *sc, int c);
+static char *readstr_upto(scheme *sc, char *delim);
+static pointer readstrexp(scheme *sc);
+static INLINE int skipspace(scheme *sc);
+static int token(scheme *sc);
+static void printslashstring(scheme *sc, char *s, int len);
+static void atom2str(scheme *sc, pointer l, int f, char **pp, int *plen);
+static void printatom(scheme *sc, pointer l, int f);
+static pointer mk_proc(scheme *sc, enum scheme_opcodes op);
+static pointer mk_closure(scheme *sc, pointer c, pointer e);
+static pointer mk_continuation(scheme *sc, pointer d);
+static pointer reverse(scheme *sc, pointer term, pointer list);
+static pointer reverse_in_place(scheme *sc, pointer term, pointer list);
+static pointer revappend(scheme *sc, pointer a, pointer b);
+static void dump_stack_preallocate_frame(scheme *sc);
+static void dump_stack_mark(scheme *);
+struct op_code_info {
+ char name[31]; /* strlen ("call-with-current-continuation") + 1 */
+ unsigned char min_arity;
+ unsigned char max_arity;
+ char arg_tests_encoding[3];
+};
+static const struct op_code_info dispatch_table[];
+static int check_arguments (scheme *sc, const struct op_code_info *pcd, char *msg, size_t msg_size);
+static void Eval_Cycle(scheme *sc, enum scheme_opcodes op);
+static void assign_syntax(scheme *sc, enum scheme_opcodes op, char *name);
+static int syntaxnum(scheme *sc, pointer p);
+static void assign_proc(scheme *sc, enum scheme_opcodes, const char *name);
+
+#define num_ivalue(n) (n.is_fixnum?(n).value.ivalue:(long)(n).value.rvalue)
+#define num_rvalue(n) (!n.is_fixnum?(n).value.rvalue:(double)(n).value.ivalue)
+
+static num num_add(num a, num b) {
+ num ret;
+ ret.is_fixnum=a.is_fixnum && b.is_fixnum;
+ if(ret.is_fixnum) {
+ ret.value.ivalue= a.value.ivalue+b.value.ivalue;
+ } else {
+ ret.value.rvalue=num_rvalue(a)+num_rvalue(b);
+ }
+ return ret;
+}
+
+static num num_mul(num a, num b) {
+ num ret;
+ ret.is_fixnum=a.is_fixnum && b.is_fixnum;
+ if(ret.is_fixnum) {
+ ret.value.ivalue= a.value.ivalue*b.value.ivalue;
+ } else {
+ ret.value.rvalue=num_rvalue(a)*num_rvalue(b);
+ }
+ return ret;
+}
+
+static num num_div(num a, num b) {
+ num ret;
+ ret.is_fixnum=a.is_fixnum && b.is_fixnum && a.value.ivalue%b.value.ivalue==0;
+ if(ret.is_fixnum) {
+ ret.value.ivalue= a.value.ivalue/b.value.ivalue;
+ } else {
+ ret.value.rvalue=num_rvalue(a)/num_rvalue(b);
+ }
+ return ret;
+}
+
+static num num_intdiv(num a, num b) {
+ num ret;
+ ret.is_fixnum=a.is_fixnum && b.is_fixnum;
+ if(ret.is_fixnum) {
+ ret.value.ivalue= a.value.ivalue/b.value.ivalue;
+ } else {
+ ret.value.rvalue=num_rvalue(a)/num_rvalue(b);
+ }
+ return ret;
+}
+
+static num num_sub(num a, num b) {
+ num ret;
+ ret.is_fixnum=a.is_fixnum && b.is_fixnum;
+ if(ret.is_fixnum) {
+ ret.value.ivalue= a.value.ivalue-b.value.ivalue;
+ } else {
+ ret.value.rvalue=num_rvalue(a)-num_rvalue(b);
+ }
+ return ret;
+}
+
+static num num_rem(num a, num b) {
+ num ret;
+ long e1, e2, res;
+ ret.is_fixnum=a.is_fixnum && b.is_fixnum;
+ e1=num_ivalue(a);
+ e2=num_ivalue(b);
+ res=e1%e2;
+ /* remainder should have same sign as second operand */
+ if (res > 0) {
+ if (e1 < 0) {
+ res -= labs(e2);
+ }
+ } else if (res < 0) {
+ if (e1 > 0) {
+ res += labs(e2);
+ }
+ }
+ ret.value.ivalue=res;
+ return ret;
+}
+
+static num num_mod(num a, num b) {
+ num ret;
+ long e1, e2, res;
+ ret.is_fixnum=a.is_fixnum && b.is_fixnum;
+ e1=num_ivalue(a);
+ e2=num_ivalue(b);
+ res=e1%e2;
+ /* modulo should have same sign as second operand */
+ if (res * e2 < 0) {
+ res += e2;
+ }
+ ret.value.ivalue=res;
+ return ret;
+}
+
+static int num_eq(num a, num b) {
+ int ret;
+ int is_fixnum=a.is_fixnum && b.is_fixnum;
+ if(is_fixnum) {
+ ret= a.value.ivalue==b.value.ivalue;
+ } else {
+ ret=num_rvalue(a)==num_rvalue(b);
+ }
+ return ret;
+}
+
+
+static int num_gt(num a, num b) {
+ int ret;
+ int is_fixnum=a.is_fixnum && b.is_fixnum;
+ if(is_fixnum) {
+ ret= a.value.ivalue>b.value.ivalue;
+ } else {
+ ret=num_rvalue(a)>num_rvalue(b);
+ }
+ return ret;
+}
+
+static int num_ge(num a, num b) {
+ return !num_lt(a,b);
+}
+
+static int num_lt(num a, num b) {
+ int ret;
+ int is_fixnum=a.is_fixnum && b.is_fixnum;
+ if(is_fixnum) {
+ ret= a.value.ivalue<b.value.ivalue;
+ } else {
+ ret=num_rvalue(a)<num_rvalue(b);
+ }
+ return ret;
+}
+
+static int num_le(num a, num b) {
+ return !num_gt(a,b);
+}
+
+#if USE_MATH
+/* Round to nearest. Round to even if midway */
+static double round_per_R5RS(double x) {
+ double fl=floor(x);
+ double ce=ceil(x);
+ double dfl=x-fl;
+ double dce=ce-x;
+ if(dfl>dce) {
+ return ce;
+ } else if(dfl<dce) {
+ return fl;
+ } else {
+ if(fmod(fl,2.0)==0.0) { /* I imagine this holds */
+ return fl;
+ } else {
+ return ce;
+ }
+ }
+}
+#endif
+
+static int is_zero_double(double x) {
+ return x<DBL_MIN && x>-DBL_MIN;
+}
+
+static long binary_decode(const char *s) {
+ long x=0;
+
+ while(*s!=0 && (*s=='1' || *s=='0')) {
+ x<<=1;
+ x+=*s-'0';
+ s++;
+ }
+
+ return x;
+}
+
+
+
+/*
+ * Copying values.
+ *
+ * Occasionally, we need to copy a value from one location in the
+ * storage to another. Scheme objects are fine. Some primitive
+ * objects, however, require finalization, usually to free resources.
+ *
+ * For these values, we either make a copy or acquire a reference.
+ */
+
+/*
+ * Copy SRC to DST.
+ *
+ * Copies the representation of SRC to DST. This makes SRC
+ * indistinguishable from DST from the perspective of a Scheme
+ * expression modulo the fact that they reside at a different location
+ * in the store.
+ *
+ * Conditions:
+ *
+ * - SRC must not be a vector.
+ * - Caller must ensure that any resources associated with the
+ * value currently stored in DST is accounted for.
+ */
+static void
+copy_value(scheme *sc, pointer dst, pointer src)
+{
+ memcpy(dst, src, sizeof *src);
+
+ /* We may need to make a copy or acquire a reference. */
+ if (typeflag(dst) & T_FINALIZE)
+ switch (type(dst)) {
+ case T_STRING:
+ strvalue(dst) = store_string(sc, strlength(dst), strvalue(dst), 0);
+ break;
+ case T_PORT:
+ /* XXX acquire reference */
+ assert (!"implemented");
+ break;
+ case T_FOREIGN_OBJECT:
+ /* XXX acquire reference */
+ assert (!"implemented");
+ break;
+ case T_VECTOR:
+ assert (!"vectors cannot be copied");
+ }
+}
+
+
+
+/* Tags are like property lists, but can be attached to arbitrary
+ * values. */
+
+static pointer
+mk_tagged_value(scheme *sc, pointer v, pointer tag_car, pointer tag_cdr)
+{
+ pointer r, t;
+
+ assert(! is_vector(v));
+
+ r = get_consecutive_cells(sc, 2);
+ if (r == sc->sink)
+ return sc->sink;
+
+ copy_value(sc, r, v);
+ typeflag(r) |= T_TAGGED;
+
+ t = r + 1;
+ typeflag(t) = T_PAIR;
+ car(t) = tag_car;
+ cdr(t) = tag_cdr;
+
+ return r;
+}
+
+static INLINE int
+has_tag(pointer v)
+{
+ return !! (typeflag(v) & T_TAGGED);
+}
+
+static INLINE pointer
+get_tag(scheme *sc, pointer v)
+{
+ if (has_tag(v))
+ return v + 1;
+ return sc->NIL;
+}
+
+
+
+/* Low-level allocator.
+ *
+ * Memory is allocated in segments. Every segment holds a fixed
+ * number of cells. Segments are linked into a list, sorted in
+ * reverse address order (i.e. those with a higher address first).
+ * This is used in the garbage collector to build the freelist in
+ * address order.
+ */
+
+struct cell_segment
+{
+ struct cell_segment *next;
+ void *alloc;
+ pointer cells;
+ size_t cells_len;
+};
+
+/* Allocate a new cell segment but do not make it available yet. */
+static int
+_alloc_cellseg(scheme *sc, size_t len, struct cell_segment **segment)
+{
+ int adj = ADJ;
+ void *cp;
+
+ if (adj < sizeof(struct cell))
+ adj = sizeof(struct cell);
+
+ /* The segment header is conveniently allocated with the cells. */
+ cp = sc->malloc(sizeof **segment + len * sizeof(struct cell) + adj);
+ if (cp == NULL)
+ return 1;
+
+ *segment = cp;
+ (*segment)->next = NULL;
+ (*segment)->alloc = cp;
+ cp = (void *) ((uintptr_t) cp + sizeof **segment);
+
+ /* adjust in TYPE_BITS-bit boundary */
+ if (((uintptr_t) cp) % adj != 0)
+ cp = (void *) (adj * ((uintptr_t) cp / adj + 1));
+
+ (*segment)->cells = cp;
+ (*segment)->cells_len = len;
+ return 0;
+}
+
+/* Deallocate a cell segment. Returns the next cell segment.
+ * Convenient for deallocation in a loop. */
+static struct cell_segment *
+_dealloc_cellseg(scheme *sc, struct cell_segment *segment)
+{
+
+ struct cell_segment *next;
+
+ if (segment == NULL)
+ return NULL;
+
+ next = segment->next;
+ sc->free(segment->alloc);
+ return next;
+}
+
+/* allocate new cell segment */
+static int alloc_cellseg(scheme *sc, int n) {
+ pointer last;
+ pointer p;
+ int k;
+
+ for (k = 0; k < n; k++) {
+ struct cell_segment *new, **s;
+ if (_alloc_cellseg(sc, CELL_SEGSIZE, &new)) {
+ return k;
+ }
+ /* insert new segment in reverse address order */
+ for (s = &sc->cell_segments;
+ *s && (uintptr_t) (*s)->alloc > (uintptr_t) new->alloc;
+ s = &(*s)->next) {
+ /* walk */
+ }
+ new->next = *s;
+ *s = new;
+
+ sc->fcells += new->cells_len;
+ last = new->cells + new->cells_len - 1;
+ for (p = new->cells; p <= last; p++) {
+ typeflag(p) = 0;
+ cdr(p) = p + 1;
+ car(p) = sc->NIL;
+ }
+ /* insert new cells in address order on free list */
+ if (sc->free_cell == sc->NIL || p < sc->free_cell) {
+ cdr(last) = sc->free_cell;
+ sc->free_cell = new->cells;
+ } else {
+ p = sc->free_cell;
+ while (cdr(p) != sc->NIL && (uintptr_t) new->cells > (uintptr_t) cdr(p))
+ p = cdr(p);
+ cdr(last) = cdr(p);
+ cdr(p) = new->cells;
+ }
+ }
+ return n;
+}
+
+
+
+/* Controlling the garbage collector.
+ *
+ * Every time a cell is allocated, the interpreter may run out of free
+ * cells and do a garbage collection. This is problematic because it
+ * might garbage collect objects that have been allocated, but are not
+ * yet made available to the interpreter.
+ *
+ * Previously, we would plug such newly allocated cells into the list
+ * of newly allocated objects rooted at car(sc->sink), but that
+ * requires allocating yet another cell increasing pressure on the
+ * memory management system.
+ *
+ * A faster alternative is to preallocate the cells needed for an
+ * operation and make sure the garbage collection is not run until all
+ * allocated objects are plugged in. This can be done with gc_disable
+ * and gc_enable.
+ */
+
+/* The garbage collector is enabled if the inhibit counter is
+ * zero. */
+#define GC_ENABLED 0
+
+/* For now we provide a way to disable this optimization for
+ * benchmarking and because it produces slightly smaller code. */
+#ifndef USE_GC_LOCKING
+# define USE_GC_LOCKING 1
+#endif
+
+/* To facilitate nested calls to gc_disable, functions that allocate
+ * more than one cell may define a macro, e.g. foo_allocates. This
+ * macro can be used to compute the amount of preallocation at the
+ * call site with the help of this macro. */
+#define gc_reservations(fn) fn ## _allocates
+
+#if USE_GC_LOCKING
+
+/* Report a shortage in reserved cells, and terminate the program. */
+static void
+gc_reservation_failure(struct scheme *sc)
+{
+#ifdef NDEBUG
+ fprintf(stderr,
+ "insufficient reservation\n");
+#else
+ fprintf(stderr,
+ "insufficient %s reservation in line %d\n",
+ sc->frame_freelist == sc->NIL ? "frame" : "cell",
+ sc->reserved_lineno);
+#endif
+ abort();
+}
+
+/* Disable the garbage collection and reserve the given number of
+ * cells. gc_disable may be nested, but the enclosing reservation
+ * must include the reservations of all nested calls. Note: You must
+ * re-enable the gc before calling Error_X. */
+static void
+_gc_disable(struct scheme *sc, size_t reserve, int lineno)
+{
+ if (sc->inhibit_gc == 0) {
+ reserve_cells(sc, (reserve));
+ sc->reserved_cells = (reserve);
+#ifdef NDEBUG
+ (void) lineno;
+#else
+ sc->reserved_lineno = lineno;
+#endif
+ } else if (sc->reserved_cells < (reserve))
+ gc_reservation_failure (sc);
+ sc->inhibit_gc += 1;
+}
+#define gc_disable(sc, reserve) \
+ do { \
+ if (sc->frame_freelist == sc->NIL) { \
+ if (gc_enabled(sc)) \
+ dump_stack_preallocate_frame(sc); \
+ else \
+ gc_reservation_failure(sc); \
+ } \
+ _gc_disable (sc, reserve, __LINE__); \
+ } while (0)
+
+/* Enable the garbage collector. */
+#define gc_enable(sc) \
+ do { \
+ assert(sc->inhibit_gc); \
+ sc->inhibit_gc -= 1; \
+ } while (0)
+
+/* Test whether the garbage collector is enabled. */
+#define gc_enabled(sc) \
+ (sc->inhibit_gc == GC_ENABLED)
+
+/* Consume a reserved cell. */
+#define gc_consume(sc) \
+ do { \
+ assert(! gc_enabled (sc)); \
+ if (sc->reserved_cells == 0) \
+ gc_reservation_failure (sc); \
+ sc->reserved_cells -= 1; \
+ } while (0)
+
+#else /* USE_GC_LOCKING */
+
+#define gc_reservation_failure(sc) (void) 0
+#define gc_disable(sc, reserve) \
+ do { \
+ if (sc->frame_freelist == sc->NIL) \
+ dump_stack_preallocate_frame(sc); \
+ } while (0)
+#define gc_enable(sc) (void) 0
+#define gc_enabled(sc) 1
+#define gc_consume(sc) (void) 0
+
+#endif /* USE_GC_LOCKING */
+
+static INLINE pointer get_cell_x(scheme *sc, pointer a, pointer b) {
+ if (! gc_enabled (sc) || sc->free_cell != sc->NIL) {
+ pointer x = sc->free_cell;
+ if (! gc_enabled (sc))
+ gc_consume (sc);
+ sc->free_cell = cdr(x);
+ --sc->fcells;
+ return (x);
+ }
+ assert (gc_enabled (sc));
+ return _get_cell (sc, a, b);
+}
+
+
+/* get new cell. parameter a, b is marked by gc. */
+static pointer _get_cell(scheme *sc, pointer a, pointer b) {
+ pointer x;
+
+ if(sc->no_memory) {
+ return sc->sink;
+ }
+
+ assert (gc_enabled (sc));
+ if (sc->free_cell == sc->NIL) {
+ gc(sc,a, b);
+ if (sc->free_cell == sc->NIL) {
+ sc->no_memory=1;
+ return sc->sink;
+ }
+ }
+ x = sc->free_cell;
+ sc->free_cell = cdr(x);
+ --sc->fcells;
+ return (x);
+}
+
+/* make sure that there is a given number of cells free */
+static pointer reserve_cells(scheme *sc, int n) {
+ if(sc->no_memory) {
+ return sc->NIL;
+ }
+
+ /* Are there enough cells available? */
+ if (sc->fcells < n) {
+ /* If not, try gc'ing some */
+ gc(sc, sc->NIL, sc->NIL);
+ if (sc->fcells < n) {
+ /* If there still aren't, try getting more heap */
+ if (!alloc_cellseg(sc,1)) {
+ sc->no_memory=1;
+ return sc->NIL;
+ }
+ }
+ if (sc->fcells < n) {
+ /* If all fail, report failure */
+ sc->no_memory=1;
+ return sc->NIL;
+ }
+ }
+ return (sc->T);
+}
+
+static pointer get_consecutive_cells(scheme *sc, int n) {
+ pointer x;
+
+ if(sc->no_memory) { return sc->sink; }
+
+ /* Are there any cells available? */
+ x=find_consecutive_cells(sc,n);
+ if (x != sc->NIL) { return x; }
+
+ /* If not, try gc'ing some */
+ gc(sc, sc->NIL, sc->NIL);
+ x=find_consecutive_cells(sc,n);
+ if (x != sc->NIL) { return x; }
+
+ /* If there still aren't, try getting more heap */
+ if (!alloc_cellseg(sc,1))
+ {
+ sc->no_memory=1;
+ return sc->sink;
+ }
+
+ x=find_consecutive_cells(sc,n);
+ if (x != sc->NIL) { return x; }
+
+ /* If all fail, report failure */
+ sc->no_memory=1;
+ return sc->sink;
+}
+
+static int count_consecutive_cells(pointer x, int needed) {
+ int n=1;
+ while(cdr(x)==x+1) {
+ x=cdr(x);
+ n++;
+ if(n>needed) return n;
+ }
+ return n;
+}
+
+static pointer find_consecutive_cells(scheme *sc, int n) {
+ pointer *pp;
+ int cnt;
+
+ pp=&sc->free_cell;
+ while(*pp!=sc->NIL) {
+ cnt=count_consecutive_cells(*pp,n);
+ if(cnt>=n) {
+ pointer x=*pp;
+ *pp=cdr(*pp+n-1);
+ sc->fcells -= n;
+ return x;
+ }
+ pp=&cdr(*pp+cnt-1);
+ }
+ return sc->NIL;
+}
+
+/* Free a cell. This is dangerous. Only free cells that are not
+ * referenced. */
+static INLINE void
+free_cell(scheme *sc, pointer a)
+{
+ cdr(a) = sc->free_cell;
+ sc->free_cell = a;
+ sc->fcells += 1;
+}
+
+/* Free a cell and retrieve its content. This is dangerous. Only
+ * free cells that are not referenced. */
+static INLINE void
+free_cons(scheme *sc, pointer a, pointer *r_car, pointer *r_cdr)
+{
+ *r_car = car(a);
+ *r_cdr = cdr(a);
+ free_cell(sc, a);
+}
+
+/* To retain recent allocs before interpreter knows about them -
+ Tehom */
+
+static void push_recent_alloc(scheme *sc, pointer recent, pointer extra)
+{
+ pointer holder = get_cell_x(sc, recent, extra);
+ typeflag(holder) = T_PAIR | T_IMMUTABLE;
+ car(holder) = recent;
+ cdr(holder) = car(sc->sink);
+ car(sc->sink) = holder;
+}
+
+static INLINE void ok_to_freely_gc(scheme *sc)
+{
+ pointer a = car(sc->sink), next;
+ car(sc->sink) = sc->NIL;
+ while (a != sc->NIL)
+ {
+ next = cdr(a);
+ free_cell(sc, a);
+ a = next;
+ }
+}
+
+static pointer get_cell(scheme *sc, pointer a, pointer b)
+{
+ pointer cell = get_cell_x(sc, a, b);
+ /* For right now, include "a" and "b" in "cell" so that gc doesn't
+ think they are garbage. */
+ /* Tentatively record it as a pair so gc understands it. */
+ typeflag(cell) = T_PAIR;
+ car(cell) = a;
+ cdr(cell) = b;
+ if (gc_enabled (sc))
+ push_recent_alloc(sc, cell, sc->NIL);
+ return cell;
+}
+
+static pointer get_vector_object(scheme *sc, int len, pointer init)
+{
+ pointer cells = get_consecutive_cells(sc, vector_size(len));
+ int i;
+ int alloc_len = 1 + 3 * (vector_size(len) - 1);
+ if(sc->no_memory) { return sc->sink; }
+ /* Record it as a vector so that gc understands it. */
+ typeflag(cells) = (T_VECTOR | T_ATOM | T_FINALIZE);
+ vector_length(cells) = len;
+ fill_vector(cells,init);
+
+ /* Initialize the unused slots at the end. */
+ assert (alloc_len - len < 3);
+ for (i = len; i < alloc_len; i++)
+ cells->_object._vector._elements[i] = sc->NIL;
+
+ if (gc_enabled (sc))
+ push_recent_alloc(sc, cells, sc->NIL);
+ return cells;
+}
+
+/* Medium level cell allocation */
+
+/* get new cons cell */
+pointer _cons(scheme *sc, pointer a, pointer b, int immutable) {
+ pointer x = get_cell(sc,a, b);
+
+ typeflag(x) = T_PAIR;
+ if(immutable) {
+ setimmutable(x);
+ }
+ car(x) = a;
+ cdr(x) = b;
+ return (x);
+}
+
+
+/* ========== oblist implementation ========== */
+
+#ifndef USE_OBJECT_LIST
+
+static int hash_fn(const char *key, int table_size);
+
+static pointer oblist_initial_value(scheme *sc)
+{
+ /* There are about 768 symbols used after loading the
+ * interpreter. */
+ return mk_vector(sc, 1009);
+}
+
+/* Lookup the symbol NAME. Returns the symbol, or NIL if it does not
+ * exist. In that case, SLOT points to the point where the new symbol
+ * is to be inserted. */
+static INLINE pointer
+oblist_find_by_name(scheme *sc, const char *name, pointer **slot)
+{
+ int location;
+ pointer x;
+ char *s;
+ int d;
+
+ location = hash_fn(name, vector_length(sc->oblist));
+ for (*slot = vector_elem_slot(sc->oblist, location), x = **slot;
+ x != sc->NIL; *slot = &cdr(x), x = **slot) {
+ s = symname(car(x));
+ /* case-insensitive, per R5RS section 2. */
+ d = stricmp(name, s);
+ if (d == 0)
+ return car(x); /* Hit. */
+ else if (d > 0)
+ break; /* Miss. */
+ }
+ return sc->NIL;
+}
+
+static pointer oblist_all_symbols(scheme *sc)
+{
+ int i;
+ pointer x;
+ pointer ob_list = sc->NIL;
+
+ for (i = 0; i < vector_length(sc->oblist); i++) {
+ for (x = vector_elem(sc->oblist, i); x != sc->NIL; x = cdr(x)) {
+ ob_list = cons(sc, x, ob_list);
+ }
+ }
+ return ob_list;
+}
+
+#else
+
+static pointer oblist_initial_value(scheme *sc)
+{
+ return sc->NIL;
+}
+
+/* Lookup the symbol NAME. Returns the symbol, or NIL if it does not
+ * exist. In that case, SLOT points to the point where the new symbol
+ * is to be inserted. */
+static INLINE pointer
+oblist_find_by_name(scheme *sc, const char *name, pointer **slot)
+{
+ pointer x;
+ char *s;
+ int d;
+
+ for (*slot = &sc->oblist, x = **slot; x != sc->NIL; *slot = &cdr(x), x = **slot) {
+ s = symname(car(x));
+ /* case-insensitive, per R5RS section 2. */
+ d = stricmp(name, s);
+ if (d == 0)
+ return car(x); /* Hit. */
+ else if (d > 0)
+ break; /* Miss. */
+ }
+ return sc->NIL;
+}
+
+static pointer oblist_all_symbols(scheme *sc)
+{
+ return sc->oblist;
+}
+
+#endif
+
+/* Add a new symbol NAME at SLOT. SLOT must be obtained using
+ * oblist_find_by_name, and no insertion must be done between
+ * obtaining the SLOT and calling this function. Returns the new
+ * symbol. */
+static pointer oblist_add_by_name(scheme *sc, const char *name, pointer *slot)
+{
+#define oblist_add_by_name_allocates 3
+ pointer x;
+
+ gc_disable(sc, gc_reservations (oblist_add_by_name));
+ x = immutable_cons(sc, mk_string(sc, name), sc->NIL);
+ typeflag(x) = T_SYMBOL;
+ setimmutable(car(x));
+ *slot = immutable_cons(sc, x, *slot);
+ gc_enable(sc);
+ return x;
+}
+
+
+
+static pointer mk_port(scheme *sc, port *p) {
+ pointer x = get_cell(sc, sc->NIL, sc->NIL);
+
+ typeflag(x) = T_PORT|T_ATOM|T_FINALIZE;
+ x->_object._port=p;
+ return (x);
+}
+
+pointer mk_foreign_func(scheme *sc, foreign_func f) {
+ pointer x = get_cell(sc, sc->NIL, sc->NIL);
+
+ typeflag(x) = (T_FOREIGN | T_ATOM);
+ x->_object._ff=f;
+ return (x);
+}
+
+pointer mk_foreign_object(scheme *sc, const foreign_object_vtable *vtable, void *data) {
+ pointer x = get_cell(sc, sc->NIL, sc->NIL);
+
+ typeflag(x) = (T_FOREIGN_OBJECT | T_ATOM | T_FINALIZE);
+ x->_object._foreign_object._vtable=vtable;
+ x->_object._foreign_object._data = data;
+ return (x);
+}
+
+INTERFACE pointer mk_character(scheme *sc, int c) {
+ pointer x = get_cell(sc,sc->NIL, sc->NIL);
+
+ typeflag(x) = (T_CHARACTER | T_ATOM);
+ ivalue_unchecked(x)= c;
+ set_num_integer(x);
+ return (x);
+}
+
+
+
+#if USE_SMALL_INTEGERS
+
+static const struct cell small_integers[] = {
+#define DEFINE_INTEGER(n) { T_NUMBER | T_ATOM | MARK, {{ 1, {n}}}},
+#include "small-integers.h"
+#undef DEFINE_INTEGER
+ {0}
+};
+
+#define MAX_SMALL_INTEGER (sizeof small_integers / sizeof *small_integers - 1)
+
+static INLINE pointer
+mk_small_integer(scheme *sc, long n)
+{
+#define mk_small_integer_allocates 0
+ (void) sc;
+ assert(0 <= n && n < MAX_SMALL_INTEGER);
+ return (pointer) &small_integers[n];
+}
+#else
+
+#define mk_small_integer_allocates 1
+#define mk_small_integer mk_integer
+
+#endif
+
+/* get number atom (integer) */
+INTERFACE pointer mk_integer(scheme *sc, long n) {
+ pointer x;
+
+#if USE_SMALL_INTEGERS
+ if (0 <= n && n < MAX_SMALL_INTEGER)
+ return mk_small_integer(sc, n);
+#endif
+
+ x = get_cell(sc,sc->NIL, sc->NIL);
+ typeflag(x) = (T_NUMBER | T_ATOM);
+ ivalue_unchecked(x)= n;
+ set_num_integer(x);
+ return (x);
+}
+
+
+
+INTERFACE pointer mk_real(scheme *sc, double n) {
+ pointer x = get_cell(sc,sc->NIL, sc->NIL);
+
+ typeflag(x) = (T_NUMBER | T_ATOM);
+ rvalue_unchecked(x)= n;
+ set_num_real(x);
+ return (x);
+}
+
+static pointer mk_number(scheme *sc, num n) {
+ if(n.is_fixnum) {
+ return mk_integer(sc,n.value.ivalue);
+ } else {
+ return mk_real(sc,n.value.rvalue);
+ }
+}
+
+/* allocate name to string area */
+static char *store_string(scheme *sc, int len_str, const char *str, char fill) {
+ char *q;
+
+ q=(char*)sc->malloc(len_str+1);
+ if(q==0) {
+ sc->no_memory=1;
+ return sc->strbuff;
+ }
+ if(str!=0) {
+ memcpy (q, str, len_str);
+ q[len_str]=0;
+ } else {
+ memset(q, fill, len_str);
+ q[len_str]=0;
+ }
+ return (q);
+}
+
+/* get new string */
+INTERFACE pointer mk_string(scheme *sc, const char *str) {
+ return mk_counted_string(sc,str,strlen(str));
+}
+
+INTERFACE pointer mk_counted_string(scheme *sc, const char *str, int len) {
+ pointer x = get_cell(sc, sc->NIL, sc->NIL);
+ typeflag(x) = (T_STRING | T_ATOM | T_FINALIZE);
+ strvalue(x) = store_string(sc,len,str,0);
+ strlength(x) = len;
+ return (x);
+}
+
+INTERFACE pointer mk_empty_string(scheme *sc, int len, char fill) {
+ pointer x = get_cell(sc, sc->NIL, sc->NIL);
+ typeflag(x) = (T_STRING | T_ATOM | T_FINALIZE);
+ strvalue(x) = store_string(sc,len,0,fill);
+ strlength(x) = len;
+ return (x);
+}
+
+INTERFACE static pointer mk_vector(scheme *sc, int len)
+{ return get_vector_object(sc,len,sc->NIL); }
+
+INTERFACE static void fill_vector(pointer vec, pointer obj) {
+ size_t i;
+ assert (is_vector (vec));
+ for(i = 0; i < vector_length(vec); i++) {
+ vec->_object._vector._elements[i] = obj;
+ }
+}
+
+INTERFACE static pointer *vector_elem_slot(pointer vec, int ielem) {
+ assert (is_vector (vec));
+ assert (ielem < vector_length(vec));
+ return &vec->_object._vector._elements[ielem];
+}
+
+INTERFACE static pointer vector_elem(pointer vec, int ielem) {
+ assert (is_vector (vec));
+ assert (ielem < vector_length(vec));
+ return vec->_object._vector._elements[ielem];
+}
+
+INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a) {
+ assert (is_vector (vec));
+ assert (ielem < vector_length(vec));
+ vec->_object._vector._elements[ielem] = a;
+ return a;
+}
+
+/* get new symbol */
+INTERFACE pointer mk_symbol(scheme *sc, const char *name) {
+#define mk_symbol_allocates oblist_add_by_name_allocates
+ pointer x;
+ pointer *slot;
+
+ /* first check oblist */
+ x = oblist_find_by_name(sc, name, &slot);
+ if (x != sc->NIL) {
+ return (x);
+ } else {
+ x = oblist_add_by_name(sc, name, slot);
+ return (x);
+ }
+}
+
+INTERFACE pointer gensym(scheme *sc) {
+ pointer x;
+ pointer *slot;
+ char name[40];
+
+ for(; sc->gensym_cnt<LONG_MAX; sc->gensym_cnt++) {
+ snprintf(name,40,"gensym-%ld",sc->gensym_cnt);
+
+ /* first check oblist */
+ x = oblist_find_by_name(sc, name, &slot);
+
+ if (x != sc->NIL) {
+ continue;
+ } else {
+ x = oblist_add_by_name(sc, name, slot);
+ return (x);
+ }
+ }
+
+ return sc->NIL;
+}
+
+/* double the size of the string buffer */
+static int expand_strbuff(scheme *sc) {
+ size_t new_size = sc->strbuff_size * 2;
+ char *new_buffer = sc->malloc(new_size);
+ if (new_buffer == 0) {
+ sc->no_memory = 1;
+ return 1;
+ }
+ memcpy(new_buffer, sc->strbuff, sc->strbuff_size);
+ sc->free(sc->strbuff);
+ sc->strbuff = new_buffer;
+ sc->strbuff_size = new_size;
+ return 0;
+}
+
+/* make symbol or number atom from string */
+static pointer mk_atom(scheme *sc, char *q) {
+ char c, *p;
+ int has_dec_point=0;
+ int has_fp_exp = 0;
+
+#if USE_COLON_HOOK
+ char *next;
+ next = p = q;
+ while ((next = strstr(next, "::")) != 0) {
+ /* Keep looking for the last occurrence. */
+ p = next;
+ next = next + 2;
+ }
+
+ if (p != q) {
+ *p=0;
+ return cons(sc, sc->COLON_HOOK,
+ cons(sc,
+ cons(sc,
+ sc->QUOTE,
+ cons(sc, mk_symbol(sc, strlwr(p + 2)),
+ sc->NIL)),
+ cons(sc, mk_atom(sc, q), sc->NIL)));
+ }
+#endif
+
+ p = q;
+ c = *p++;
+ if ((c == '+') || (c == '-')) {
+ c = *p++;
+ if (c == '.') {
+ has_dec_point=1;
+ c = *p++;
+ }
+ if (!isdigit(c)) {
+ return (mk_symbol(sc, strlwr(q)));
+ }
+ } else if (c == '.') {
+ has_dec_point=1;
+ c = *p++;
+ if (!isdigit(c)) {
+ return (mk_symbol(sc, strlwr(q)));
+ }
+ } else if (!isdigit(c)) {
+ return (mk_symbol(sc, strlwr(q)));
+ }
+
+ for ( ; (c = *p) != 0; ++p) {
+ if (!isdigit(c)) {
+ if(c=='.') {
+ if(!has_dec_point) {
+ has_dec_point=1;
+ continue;
+ }
+ }
+ else if ((c == 'e') || (c == 'E')) {
+ if(!has_fp_exp) {
+ has_dec_point = 1; /* decimal point illegal
+ from now on */
+ p++;
+ if ((*p == '-') || (*p == '+') || isdigit(*p)) {
+ continue;
+ }
+ }
+ }
+ return (mk_symbol(sc, strlwr(q)));
+ }
+ }
+ if(has_dec_point) {
+ return mk_real(sc,atof(q));
+ }
+ return (mk_integer(sc, atol(q)));
+}
+
+/* make constant */
+static pointer mk_sharp_const(scheme *sc, char *name) {
+ long x;
+ char tmp[STRBUFFSIZE];
+
+ if (!strcmp(name, "t"))
+ return (sc->T);
+ else if (!strcmp(name, "f"))
+ return (sc->F);
+ else if (*name == 'o') {/* #o (octal) */
+ snprintf(tmp, STRBUFFSIZE, "0%s", name+1);
+ sscanf(tmp, "%lo", (long unsigned *)&x);
+ return (mk_integer(sc, x));
+ } else if (*name == 'd') { /* #d (decimal) */
+ sscanf(name+1, "%ld", (long int *)&x);
+ return (mk_integer(sc, x));
+ } else if (*name == 'x') { /* #x (hex) */
+ snprintf(tmp, STRBUFFSIZE, "0x%s", name+1);
+ sscanf(tmp, "%lx", (long unsigned *)&x);
+ return (mk_integer(sc, x));
+ } else if (*name == 'b') { /* #b (binary) */
+ x = binary_decode(name+1);
+ return (mk_integer(sc, x));
+ } else if (*name == '\\') { /* #\w (character) */
+ int c=0;
+ if(stricmp(name+1,"space")==0) {
+ c=' ';
+ } else if(stricmp(name+1,"newline")==0) {
+ c='\n';
+ } else if(stricmp(name+1,"return")==0) {
+ c='\r';
+ } else if(stricmp(name+1,"tab")==0) {
+ c='\t';
+ } else if(name[1]=='x' && name[2]!=0) {
+ int c1=0;
+ if(sscanf(name+2,"%x",(unsigned int *)&c1)==1 && c1 < UCHAR_MAX) {
+ c=c1;
+ } else {
+ return sc->NIL;
+ }
+#if USE_ASCII_NAMES
+ } else if(is_ascii_name(name+1,&c)) {
+ /* nothing */
+#endif
+ } else if(name[2]==0) {
+ c=name[1];
+ } else {
+ return sc->NIL;
+ }
+ return mk_character(sc,c);
+ } else
+ return (sc->NIL);
+}
+
+/* ========== garbage collector ========== */
+
+const int frame_length;
+static void dump_stack_deallocate_frame(scheme *sc, pointer frame);
+
+/*--
+ * We use algorithm E (Knuth, The Art of Computer Programming Vol.1,
+ * sec. 2.3.5), the Schorr-Deutsch-Waite link-inversion algorithm,
+ * for marking.
+ */
+static void mark(pointer a) {
+ pointer t, q, p;
+
+ t = (pointer) 0;
+ p = a;
+E2: if (! is_mark(p))
+ setmark(p);
+ if (is_vector(p) || is_frame(p)) {
+ int i;
+ int len = is_vector(p) ? vector_length(p) : frame_length;
+ for (i = 0; i < len; i++) {
+ mark(p->_object._vector._elements[i]);
+ }
+ }
+#if SHOW_ERROR_LINE
+ else if (is_port(p)) {
+ port *pt = p->_object._port;
+ mark(pt->curr_line);
+ mark(pt->filename);
+ }
+#endif
+ /* Mark tag if p has one. */
+ if (has_tag(p))
+ mark(p + 1);
+ if (is_atom(p))
+ goto E6;
+ /* E4: down car */
+ q = car(p);
+ if (q && !is_mark(q)) {
+ setatom(p); /* a note that we have moved car */
+ car(p) = t;
+ t = p;
+ p = q;
+ goto E2;
+ }
+E5: q = cdr(p); /* down cdr */
+ if (q && !is_mark(q)) {
+ cdr(p) = t;
+ t = p;
+ p = q;
+ goto E2;
+ }
+E6: /* up. Undo the link switching from steps E4 and E5. */
+ if (!t)
+ return;
+ q = t;
+ if (is_atom(q)) {
+ clratom(q);
+ t = car(q);
+ car(q) = p;
+ p = q;
+ goto E5;
+ } else {
+ t = cdr(q);
+ cdr(q) = p;
+ p = q;
+ goto E6;
+ }
+}
+
+/* garbage collection. parameter a, b is marked. */
+static void gc(scheme *sc, pointer a, pointer b) {
+ pointer p;
+ struct cell_segment *s;
+ int i;
+
+ assert (gc_enabled (sc));
+
+ if(sc->gc_verbose) {
+ putstr(sc, "gc...");
+ }
+
+ /* mark system globals */
+ mark(sc->oblist);
+ mark(sc->global_env);
+
+ /* mark current registers */
+ mark(sc->args);
+ mark(sc->envir);
+ mark(sc->code);
+ history_mark(sc);
+ dump_stack_mark(sc);
+ mark(sc->value);
+ mark(sc->inport);
+ mark(sc->save_inport);
+ mark(sc->outport);
+ mark(sc->loadport);
+ for (i = 0; i <= sc->file_i; i++) {
+ mark(sc->load_stack[i].filename);
+ mark(sc->load_stack[i].curr_line);
+ }
+
+ /* Mark recent objects the interpreter doesn't know about yet. */
+ mark(car(sc->sink));
+ /* Mark any older stuff above nested C calls */
+ mark(sc->c_nest);
+
+ /* mark variables a, b */
+ mark(a);
+ mark(b);
+
+ /* garbage collect */
+ clrmark(sc->NIL);
+ sc->fcells = 0;
+ sc->free_cell = sc->NIL;
+ /* free-list is kept sorted by address so as to maintain consecutive
+ ranges, if possible, for use with vectors. Here we scan the cells
+ (which are also kept sorted by address) downwards to build the
+ free-list in sorted order.
+ */
+ for (s = sc->cell_segments; s; s = s->next) {
+ p = s->cells + s->cells_len;
+ while (--p >= s->cells) {
+ if ((typeflag(p) & 1) == 0)
+ /* All types have the LSB set. This is not a typeflag. */
+ continue;
+ if (is_mark(p)) {
+ clrmark(p);
+ } else {
+ /* reclaim cell */
+ if ((typeflag(p) & T_FINALIZE) == 0
+ || finalize_cell(sc, p)) {
+ /* Reclaim cell. */
+ ++sc->fcells;
+ typeflag(p) = 0;
+ car(p) = sc->NIL;
+ cdr(p) = sc->free_cell;
+ sc->free_cell = p;
+ }
+ }
+ }
+ }
+
+ if (sc->gc_verbose) {
+ char msg[80];
+ snprintf(msg,80,"done: %ld cells were recovered.\n", sc->fcells);
+ putstr(sc,msg);
+ }
+
+ /* if only a few recovered, get more to avoid fruitless gc's */
+ if (sc->fcells < CELL_MINRECOVER
+ && alloc_cellseg(sc, 1) == 0)
+ sc->no_memory = 1;
+}
+
+/* Finalize A. Returns true if a can be added to the list of free
+ * cells. */
+static int
+finalize_cell(scheme *sc, pointer a)
+{
+ switch (type(a)) {
+ case T_STRING:
+ sc->free(strvalue(a));
+ break;
+
+ case T_PORT:
+ if(a->_object._port->kind&port_file
+ && a->_object._port->rep.stdio.closeit) {
+ port_close(sc,a,port_input|port_output);
+ } else if (a->_object._port->kind & port_srfi6) {
+ sc->free(a->_object._port->rep.string.start);
+ }
+ sc->free(a->_object._port);
+ break;
+
+ case T_FOREIGN_OBJECT:
+ a->_object._foreign_object._vtable->finalize(sc, a->_object._foreign_object._data);
+ break;
+
+ case T_VECTOR:
+ do {
+ int i;
+ for (i = vector_size(vector_length(a)) - 1; i > 0; i--) {
+ pointer p = a + i;
+ typeflag(p) = 0;
+ car(p) = sc->NIL;
+ cdr(p) = sc->free_cell;
+ sc->free_cell = p;
+ sc->fcells += 1;
+ }
+ } while (0);
+ break;
+
+ case T_FRAME:
+ dump_stack_deallocate_frame(sc, a);
+ return 0; /* Do not free cell. */
+ }
+
+ return 1; /* Free cell. */
+}
+
+#if SHOW_ERROR_LINE
+static void
+port_clear_location (scheme *sc, port *p)
+{
+ p->curr_line = sc->NIL;
+ p->filename = sc->NIL;
+}
+
+static void
+port_increment_current_line (scheme *sc, port *p, long delta)
+{
+ if (delta == 0)
+ return;
+
+ p->curr_line =
+ mk_integer(sc, ivalue_unchecked(p->curr_line) + delta);
+}
+
+static void
+port_init_location (scheme *sc, port *p, pointer name)
+{
+ p->curr_line = mk_integer(sc, 0);
+ p->filename = name ? name : mk_string(sc, "<unknown>");
+}
+
+#else
+
+static void
+port_clear_location (scheme *sc, port *p)
+{
+}
+
+static void
+port_increment_current_line (scheme *sc, port *p, long delta)
+{
+}
+
+static void
+port_init_location (scheme *sc, port *p, pointer name)
+{
+}
+
+#endif
+
+/* ========== Routines for Reading ========== */
+
+static int file_push(scheme *sc, pointer fname) {
+ FILE *fin = NULL;
+
+ if (sc->file_i == MAXFIL-1)
+ return 0;
+ fin = fopen(string_value(fname), "r");
+ if(fin!=0) {
+ sc->file_i++;
+ sc->load_stack[sc->file_i].kind=port_file|port_input;
+ sc->load_stack[sc->file_i].rep.stdio.file=fin;
+ sc->load_stack[sc->file_i].rep.stdio.closeit=1;
+ sc->nesting_stack[sc->file_i]=0;
+ sc->loadport->_object._port=sc->load_stack+sc->file_i;
+ port_init_location(sc, &sc->load_stack[sc->file_i], fname);
+ }
+ return fin!=0;
+}
+
+static void file_pop(scheme *sc) {
+ if(sc->file_i != 0) {
+ sc->nesting=sc->nesting_stack[sc->file_i];
+ port_close(sc,sc->loadport,port_input);
+ port_clear_location(sc, &sc->load_stack[sc->file_i]);
+ sc->file_i--;
+ sc->loadport->_object._port=sc->load_stack+sc->file_i;
+ }
+}
+
+static int file_interactive(scheme *sc) {
+ return sc->file_i==0 && sc->load_stack[0].rep.stdio.file==stdin
+ && sc->inport->_object._port->kind&port_file;
+}
+
+static port *port_rep_from_filename(scheme *sc, const char *fn, int prop) {
+ FILE *f;
+ char *rw;
+ port *pt;
+ if(prop==(port_input|port_output)) {
+ rw="a+";
+ } else if(prop==port_output) {
+ rw="w";
+ } else {
+ rw="r";
+ }
+ f=fopen(fn,rw);
+ if(f==0) {
+ return 0;
+ }
+ pt=port_rep_from_file(sc,f,prop);
+ pt->rep.stdio.closeit=1;
+ port_init_location(sc, pt, mk_string(sc, fn));
+ return pt;
+}
+
+static pointer port_from_filename(scheme *sc, const char *fn, int prop) {
+ port *pt;
+ pt=port_rep_from_filename(sc,fn,prop);
+ if(pt==0) {
+ return sc->NIL;
+ }
+ return mk_port(sc,pt);
+}
+
+static port *port_rep_from_file(scheme *sc, FILE *f, int prop)
+{
+ port *pt;
+
+ pt = (port *)sc->malloc(sizeof *pt);
+ if (pt == NULL) {
+ return NULL;
+ }
+ pt->kind = port_file | prop;
+ pt->rep.stdio.file = f;
+ pt->rep.stdio.closeit = 0;
+ port_init_location(sc, pt, NULL);
+ return pt;
+}
+
+static pointer port_from_file(scheme *sc, FILE *f, int prop) {
+ port *pt;
+ pt=port_rep_from_file(sc,f,prop);
+ if(pt==0) {
+ return sc->NIL;
+ }
+ return mk_port(sc,pt);
+}
+
+static port *port_rep_from_string(scheme *sc, char *start, char *past_the_end, int prop) {
+ port *pt;
+ pt=(port*)sc->malloc(sizeof(port));
+ if(pt==0) {
+ return 0;
+ }
+ pt->kind=port_string|prop;
+ pt->rep.string.start=start;
+ pt->rep.string.curr=start;
+ pt->rep.string.past_the_end=past_the_end;
+ port_init_location(sc, pt, NULL);
+ return pt;
+}
+
+static pointer port_from_string(scheme *sc, char *start, char *past_the_end, int prop) {
+ port *pt;
+ pt=port_rep_from_string(sc,start,past_the_end,prop);
+ if(pt==0) {
+ return sc->NIL;
+ }
+ return mk_port(sc,pt);
+}
+
+#define BLOCK_SIZE 256
+
+static port *port_rep_from_scratch(scheme *sc) {
+ port *pt;
+ char *start;
+ pt=(port*)sc->malloc(sizeof(port));
+ if(pt==0) {
+ return 0;
+ }
+ start=sc->malloc(BLOCK_SIZE);
+ if(start==0) {
+ return 0;
+ }
+ memset(start,' ',BLOCK_SIZE-1);
+ start[BLOCK_SIZE-1]='\0';
+ pt->kind=port_string|port_output|port_srfi6;
+ pt->rep.string.start=start;
+ pt->rep.string.curr=start;
+ pt->rep.string.past_the_end=start+BLOCK_SIZE-1;
+ port_init_location(sc, pt, NULL);
+ return pt;
+}
+
+static pointer port_from_scratch(scheme *sc) {
+ port *pt;
+ pt=port_rep_from_scratch(sc);
+ if(pt==0) {
+ return sc->NIL;
+ }
+ return mk_port(sc,pt);
+}
+
+static void port_close(scheme *sc, pointer p, int flag) {
+ port *pt=p->_object._port;
+ pt->kind&=~flag;
+ if((pt->kind & (port_input|port_output))==0) {
+ /* Cleanup is here so (close-*-port) functions could work too */
+ port_clear_location(sc, pt);
+ if(pt->kind&port_file) {
+ fclose(pt->rep.stdio.file);
+ }
+ pt->kind=port_free;
+ }
+}
+
+/* get new character from input file */
+static int inchar(scheme *sc) {
+ int c;
+ port *pt;
+
+ pt = sc->inport->_object._port;
+ if(pt->kind & port_saw_EOF)
+ { return EOF; }
+ c = basic_inchar(pt);
+ if(c == EOF && sc->inport == sc->loadport) {
+ /* Instead, set port_saw_EOF */
+ pt->kind |= port_saw_EOF;
+
+ /* file_pop(sc); */
+ return EOF;
+ /* NOTREACHED */
+ }
+ return c;
+}
+
+static int basic_inchar(port *pt) {
+ if(pt->kind & port_file) {
+ return fgetc(pt->rep.stdio.file);
+ } else {
+ if(*pt->rep.string.curr == 0 ||
+ pt->rep.string.curr == pt->rep.string.past_the_end) {
+ return EOF;
+ } else {
+ return *pt->rep.string.curr++;
+ }
+ }
+}
+
+/* back character to input buffer */
+static void backchar(scheme *sc, int c) {
+ port *pt;
+ if(c==EOF) return;
+ pt=sc->inport->_object._port;
+ if(pt->kind&port_file) {
+ ungetc(c,pt->rep.stdio.file);
+ } else {
+ if(pt->rep.string.curr!=pt->rep.string.start) {
+ --pt->rep.string.curr;
+ }
+ }
+}
+
+static int realloc_port_string(scheme *sc, port *p)
+{
+ char *start=p->rep.string.start;
+ size_t old_size = p->rep.string.past_the_end - start;
+ size_t new_size=p->rep.string.past_the_end-start+1+BLOCK_SIZE;
+ char *str=sc->malloc(new_size);
+ if(str) {
+ memset(str,' ',new_size-1);
+ str[new_size-1]='\0';
+ memcpy(str, start, old_size);
+ p->rep.string.start=str;
+ p->rep.string.past_the_end=str+new_size-1;
+ p->rep.string.curr-=start-str;
+ sc->free(start);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+INTERFACE void putstr(scheme *sc, const char *s) {
+ port *pt=sc->outport->_object._port;
+ if(pt->kind&port_file) {
+ fputs(s,pt->rep.stdio.file);
+ } else {
+ for(;*s;s++) {
+ if(pt->rep.string.curr!=pt->rep.string.past_the_end) {
+ *pt->rep.string.curr++=*s;
+ } else if(pt->kind&port_srfi6&&realloc_port_string(sc,pt)) {
+ *pt->rep.string.curr++=*s;
+ }
+ }
+ }
+}
+
+static void putchars(scheme *sc, const char *s, int len) {
+ port *pt=sc->outport->_object._port;
+ if(pt->kind&port_file) {
+ fwrite(s,1,len,pt->rep.stdio.file);
+ } else {
+ for(;len;len--) {
+ if(pt->rep.string.curr!=pt->rep.string.past_the_end) {
+ *pt->rep.string.curr++=*s++;
+ } else if(pt->kind&port_srfi6&&realloc_port_string(sc,pt)) {
+ *pt->rep.string.curr++=*s++;
+ }
+ }
+ }
+}
+
+INTERFACE void putcharacter(scheme *sc, int c) {
+ port *pt=sc->outport->_object._port;
+ if(pt->kind&port_file) {
+ fputc(c,pt->rep.stdio.file);
+ } else {
+ if(pt->rep.string.curr!=pt->rep.string.past_the_end) {
+ *pt->rep.string.curr++=c;
+ } else if(pt->kind&port_srfi6&&realloc_port_string(sc,pt)) {
+ *pt->rep.string.curr++=c;
+ }
+ }
+}
+
+/* read characters up to delimiter, but cater to character constants */
+static char *readstr_upto(scheme *sc, char *delim) {
+ char *p = sc->strbuff;
+
+ while ((p - sc->strbuff < sc->strbuff_size) &&
+ !is_one_of(delim, (*p++ = inchar(sc))));
+
+ if(p == sc->strbuff+2 && p[-2] == '\\') {
+ *p=0;
+ } else {
+ backchar(sc,p[-1]);
+ *--p = '\0';
+ }
+ return sc->strbuff;
+}
+
+/* read string expression "xxx...xxx" */
+static pointer readstrexp(scheme *sc) {
+ char *p = sc->strbuff;
+ int c;
+ int c1=0;
+ enum { st_ok, st_bsl, st_x1, st_x2, st_oct1, st_oct2 } state=st_ok;
+
+ for (;;) {
+ c=inchar(sc);
+ if(c == EOF) {
+ return sc->F;
+ }
+ if(p-sc->strbuff > (sc->strbuff_size)-1) {
+ ptrdiff_t offset = p - sc->strbuff;
+ if (expand_strbuff(sc) != 0) {
+ return sc->F;
+ }
+ p = sc->strbuff + offset;
+ }
+ switch(state) {
+ case st_ok:
+ switch(c) {
+ case '\\':
+ state=st_bsl;
+ break;
+ case '"':
+ *p=0;
+ return mk_counted_string(sc,sc->strbuff,p-sc->strbuff);
+ default:
+ *p++=c;
+ break;
+ }
+ break;
+ case st_bsl:
+ switch(c) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ state=st_oct1;
+ c1=c-'0';
+ break;
+ case 'x':
+ case 'X':
+ state=st_x1;
+ c1=0;
+ break;
+ case 'n':
+ *p++='\n';
+ state=st_ok;
+ break;
+ case 't':
+ *p++='\t';
+ state=st_ok;
+ break;
+ case 'r':
+ *p++='\r';
+ state=st_ok;
+ break;
+ case '"':
+ *p++='"';
+ state=st_ok;
+ break;
+ default:
+ *p++=c;
+ state=st_ok;
+ break;
+ }
+ break;
+ case st_x1:
+ case st_x2:
+ c=toupper(c);
+ if(c>='0' && c<='F') {
+ if(c<='9') {
+ c1=(c1<<4)+c-'0';
+ } else {
+ c1=(c1<<4)+c-'A'+10;
+ }
+ if(state==st_x1) {
+ state=st_x2;
+ } else {
+ *p++=c1;
+ state=st_ok;
+ }
+ } else {
+ return sc->F;
+ }
+ break;
+ case st_oct1:
+ case st_oct2:
+ if (c < '0' || c > '7')
+ {
+ *p++=c1;
+ backchar(sc, c);
+ state=st_ok;
+ }
+ else
+ {
+ if (state==st_oct2 && c1 >= 32)
+ return sc->F;
+
+ c1=(c1<<3)+(c-'0');
+
+ if (state == st_oct1)
+ state=st_oct2;
+ else
+ {
+ *p++=c1;
+ state=st_ok;
+ }
+ }
+ break;
+
+ }
+ }
+}
+
+/* check c is in chars */
+static INLINE int is_one_of(char *s, int c) {
+ if(c==EOF) return 1;
+ while (*s)
+ if (*s++ == c)
+ return (1);
+ return (0);
+}
+
+/* skip white characters */
+static INLINE int skipspace(scheme *sc) {
+ int c = 0, curr_line = 0;
+
+ do {
+ c=inchar(sc);
+#if SHOW_ERROR_LINE
+ if(c=='\n')
+ curr_line++;
+#endif
+ } while (isspace(c));
+
+ /* record it */
+ port_increment_current_line(sc, &sc->load_stack[sc->file_i], curr_line);
+
+ if(c!=EOF) {
+ backchar(sc,c);
+ return 1;
+ }
+ else
+ { return EOF; }
+}
+
+/* get token */
+static int token(scheme *sc) {
+ int c;
+ c = skipspace(sc);
+ if(c == EOF) { return (TOK_EOF); }
+ switch (c=inchar(sc)) {
+ case EOF:
+ return (TOK_EOF);
+ case '(':
+ return (TOK_LPAREN);
+ case ')':
+ return (TOK_RPAREN);
+ case '.':
+ c=inchar(sc);
+ if(is_one_of(" \n\t",c)) {
+ return (TOK_DOT);
+ } else {
+ backchar(sc,c);
+ backchar(sc,'.');
+ return TOK_ATOM;
+ }
+ case '\'':
+ return (TOK_QUOTE);
+ case ';':
+ while ((c=inchar(sc)) != '\n' && c!=EOF)
+ ;
+
+ if(c == '\n')
+ port_increment_current_line(sc, &sc->load_stack[sc->file_i], 1);
+
+ if(c == EOF)
+ { return (TOK_EOF); }
+ else
+ { return (token(sc));}
+ case '"':
+ return (TOK_DQUOTE);
+ case BACKQUOTE:
+ return (TOK_BQUOTE);
+ case ',':
+ if ((c=inchar(sc)) == '@') {
+ return (TOK_ATMARK);
+ } else {
+ backchar(sc,c);
+ return (TOK_COMMA);
+ }
+ case '#':
+ c=inchar(sc);
+ if (c == '(') {
+ return (TOK_VEC);
+ } else if(c == '!') {
+ while ((c=inchar(sc)) != '\n' && c!=EOF)
+ ;
+
+ if(c == '\n')
+ port_increment_current_line(sc, &sc->load_stack[sc->file_i], 1);
+
+ if(c == EOF)
+ { return (TOK_EOF); }
+ else
+ { return (token(sc));}
+ } else {
+ backchar(sc,c);
+ if(is_one_of(" tfodxb\\",c)) {
+ return TOK_SHARP_CONST;
+ } else {
+ return (TOK_SHARP);
+ }
+ }
+ default:
+ backchar(sc,c);
+ return (TOK_ATOM);
+ }
+}
+
+/* ========== Routines for Printing ========== */
+#define ok_abbrev(x) (is_pair(x) && cdr(x) == sc->NIL)
+
+static void printslashstring(scheme *sc, char *p, int len) {
+ int i;
+ unsigned char *s=(unsigned char*)p;
+ putcharacter(sc,'"');
+ for ( i=0; i<len; i++) {
+ if(*s==0xff || *s=='"' || *s<' ' || *s=='\\') {
+ putcharacter(sc,'\\');
+ switch(*s) {
+ case '"':
+ putcharacter(sc,'"');
+ break;
+ case '\n':
+ putcharacter(sc,'n');
+ break;
+ case '\t':
+ putcharacter(sc,'t');
+ break;
+ case '\r':
+ putcharacter(sc,'r');
+ break;
+ case '\\':
+ putcharacter(sc,'\\');
+ break;
+ default: {
+ int d=*s/16;
+ putcharacter(sc,'x');
+ if(d<10) {
+ putcharacter(sc,d+'0');
+ } else {
+ putcharacter(sc,d-10+'A');
+ }
+ d=*s%16;
+ if(d<10) {
+ putcharacter(sc,d+'0');
+ } else {
+ putcharacter(sc,d-10+'A');
+ }
+ }
+ }
+ } else {
+ putcharacter(sc,*s);
+ }
+ s++;
+ }
+ putcharacter(sc,'"');
+}
+
+
+/* print atoms */
+static void printatom(scheme *sc, pointer l, int f) {
+ char *p;
+ int len;
+ atom2str(sc,l,f,&p,&len);
+ putchars(sc,p,len);
+}
+
+
+/* Uses internal buffer unless string pointer is already available */
+static void atom2str(scheme *sc, pointer l, int f, char **pp, int *plen) {
+ char *p;
+
+ if (l == sc->NIL) {
+ p = "()";
+ } else if (l == sc->T) {
+ p = "#t";
+ } else if (l == sc->F) {
+ p = "#f";
+ } else if (l == sc->EOF_OBJ) {
+ p = "#<EOF>";
+ } else if (is_port(l)) {
+ p = "#<PORT>";
+ } else if (is_number(l)) {
+ p = sc->strbuff;
+ if (f <= 1 || f == 10) /* f is the base for numbers if > 1 */ {
+ if(num_is_integer(l)) {
+ snprintf(p, STRBUFFSIZE, "%ld", ivalue_unchecked(l));
+ } else {
+ snprintf(p, STRBUFFSIZE, "%.10g", rvalue_unchecked(l));
+ /* r5rs says there must be a '.' (unless 'e'?) */
+ f = strcspn(p, ".e");
+ if (p[f] == 0) {
+ p[f] = '.'; /* not found, so add '.0' at the end */
+ p[f+1] = '0';
+ p[f+2] = 0;
+ }
+ }
+ } else {
+ long v = ivalue(l);
+ if (f == 16) {
+ if (v >= 0)
+ snprintf(p, STRBUFFSIZE, "%lx", v);
+ else
+ snprintf(p, STRBUFFSIZE, "-%lx", -v);
+ } else if (f == 8) {
+ if (v >= 0)
+ snprintf(p, STRBUFFSIZE, "%lo", v);
+ else
+ snprintf(p, STRBUFFSIZE, "-%lo", -v);
+ } else if (f == 2) {
+ unsigned long b = (v < 0) ? -v : v;
+ p = &p[STRBUFFSIZE-1];
+ *p = 0;
+ do { *--p = (b&1) ? '1' : '0'; b >>= 1; } while (b != 0);
+ if (v < 0) *--p = '-';
+ }
+ }
+ } else if (is_string(l)) {
+ if (!f) {
+ *pp = strvalue(l);
+ *plen = strlength(l);
+ return;
+ } else { /* Hack, uses the fact that printing is needed */
+ *pp=sc->strbuff;
+ *plen=0;
+ printslashstring(sc, strvalue(l), strlength(l));
+ return;
+ }
+ } else if (is_character(l)) {
+ int c=charvalue(l);
+ p = sc->strbuff;
+ if (!f) {
+ p[0]=c;
+ p[1]=0;
+ } else {
+ switch(c) {
+ case ' ':
+ p = "#\\space";
+ break;
+ case '\n':
+ p = "#\\newline";
+ break;
+ case '\r':
+ p = "#\\return";
+ break;
+ case '\t':
+ p = "#\\tab";
+ break;
+ default:
+#if USE_ASCII_NAMES
+ if(c==127) {
+ p = "#\\del";
+ break;
+ } else if(c<32) {
+ snprintf(p,STRBUFFSIZE, "#\\%s",charnames[c]);
+ break;
+ }
+#else
+ if(c<32) {
+ snprintf(p,STRBUFFSIZE,"#\\x%x",c);
+ break;
+ }
+#endif
+ snprintf(p,STRBUFFSIZE,"#\\%c",c);
+ break;
+ }
+ }
+ } else if (is_symbol(l)) {
+ p = symname(l);
+ } else if (is_proc(l)) {
+ p = sc->strbuff;
+ snprintf(p,STRBUFFSIZE,"#<%s PROCEDURE %ld>", procname(l),procnum(l));
+ } else if (is_macro(l)) {
+ p = "#<MACRO>";
+ } else if (is_closure(l)) {
+ p = "#<CLOSURE>";
+ } else if (is_promise(l)) {
+ p = "#<PROMISE>";
+ } else if (is_foreign(l)) {
+ p = sc->strbuff;
+ snprintf(p,STRBUFFSIZE,"#<FOREIGN PROCEDURE %ld>", procnum(l));
+ } else if (is_continuation(l)) {
+ p = "#<CONTINUATION>";
+ } else if (is_foreign_object(l)) {
+ p = sc->strbuff;
+ l->_object._foreign_object._vtable->to_string(sc, p, STRBUFFSIZE, l->_object._foreign_object._data);
+ } else {
+ p = "#<ERROR>";
+ }
+ *pp=p;
+ *plen=strlen(p);
+}
+/* ========== Routines for Evaluation Cycle ========== */
+
+/* make closure. c is code. e is environment */
+static pointer mk_closure(scheme *sc, pointer c, pointer e) {
+ pointer x = get_cell(sc, c, e);
+
+ typeflag(x) = T_CLOSURE;
+ car(x) = c;
+ cdr(x) = e;
+ return (x);
+}
+
+/* make continuation. */
+static pointer mk_continuation(scheme *sc, pointer d) {
+ pointer x = get_cell(sc, sc->NIL, d);
+
+ typeflag(x) = T_CONTINUATION;
+ cont_dump(x) = d;
+ return (x);
+}
+
+static pointer list_star(scheme *sc, pointer d) {
+ pointer p, q;
+ if(cdr(d)==sc->NIL) {
+ return car(d);
+ }
+ p=cons(sc,car(d),cdr(d));
+ q=p;
+ while(cdr(cdr(p))!=sc->NIL) {
+ d=cons(sc,car(p),cdr(p));
+ if(cdr(cdr(p))!=sc->NIL) {
+ p=cdr(d);
+ }
+ }
+ cdr(p)=car(cdr(p));
+ return q;
+}
+
+/* reverse list -- produce new list */
+static pointer reverse(scheme *sc, pointer term, pointer list) {
+/* a must be checked by gc */
+ pointer a = list, p = term;
+
+ for ( ; is_pair(a); a = cdr(a)) {
+ p = cons(sc, car(a), p);
+ }
+ return (p);
+}
+
+/* reverse list --- in-place */
+static pointer reverse_in_place(scheme *sc, pointer term, pointer list) {
+ pointer p = list, result = term, q;
+
+ while (p != sc->NIL) {
+ q = cdr(p);
+ cdr(p) = result;
+ result = p;
+ p = q;
+ }
+ return (result);
+}
+
+/* append list -- produce new list (in reverse order) */
+static pointer revappend(scheme *sc, pointer a, pointer b) {
+ pointer result = a;
+ pointer p = b;
+
+ while (is_pair(p)) {
+ result = cons(sc, car(p), result);
+ p = cdr(p);
+ }
+
+ if (p == sc->NIL) {
+ return result;
+ }
+
+ return sc->F; /* signal an error */
+}
+
+/* equivalence of atoms */
+int eqv(pointer a, pointer b) {
+ if (is_string(a)) {
+ if (is_string(b))
+ return (strvalue(a) == strvalue(b));
+ else
+ return (0);
+ } else if (is_number(a)) {
+ if (is_number(b)) {
+ if (num_is_integer(a) == num_is_integer(b))
+ return num_eq(nvalue(a),nvalue(b));
+ }
+ return (0);
+ } else if (is_character(a)) {
+ if (is_character(b))
+ return charvalue(a)==charvalue(b);
+ else
+ return (0);
+ } else if (is_port(a)) {
+ if (is_port(b))
+ return a==b;
+ else
+ return (0);
+ } else if (is_proc(a)) {
+ if (is_proc(b))
+ return procnum(a)==procnum(b);
+ else
+ return (0);
+ } else {
+ return (a == b);
+ }
+}
+
+/* true or false value macro */
+/* () is #t in R5RS */
+#define is_true(p) ((p) != sc->F)
+#define is_false(p) ((p) == sc->F)
+
+
+/* ========== Environment implementation ========== */
+
+#if !defined(USE_ALIST_ENV) || !defined(USE_OBJECT_LIST)
+
+static int hash_fn(const char *key, int table_size)
+{
+ unsigned int hashed = 0;
+ const char *c;
+ int bits_per_int = sizeof(unsigned int)*8;
+
+ for (c = key; *c; c++) {
+ /* letters have about 5 bits in them */
+ hashed = (hashed<<5) | (hashed>>(bits_per_int-5));
+ hashed ^= *c;
+ }
+ return hashed % table_size;
+}
+#endif
+
+/* Compares A and B. Returns an integer less than, equal to, or
+ * greater than zero if A is stored at a memory location that is
+ * numerical less than, equal to, or greater than that of B. */
+static int
+pointercmp(pointer a, pointer b)
+{
+ uintptr_t a_n = (uintptr_t) a;
+ uintptr_t b_n = (uintptr_t) b;
+
+ if (a_n < b_n)
+ return -1;
+ if (a_n > b_n)
+ return 1;
+ return 0;
+}
+
+#ifndef USE_ALIST_ENV
+
+/*
+ * In this implementation, each frame of the environment may be
+ * a hash table: a vector of alists hashed by variable name.
+ * In practice, we use a vector only for the initial frame;
+ * subsequent frames are too small and transient for the lookup
+ * speed to out-weigh the cost of making a new vector.
+ */
+
+static void new_frame_in_env(scheme *sc, pointer old_env)
+{
+ pointer new_frame;
+
+ /* The interaction-environment has about 480 variables in it. */
+ if (old_env == sc->NIL) {
+ new_frame = mk_vector(sc, 751);
+ } else {
+ new_frame = sc->NIL;
+ }
+
+ gc_disable(sc, 1);
+ sc->envir = immutable_cons(sc, new_frame, old_env);
+ gc_enable(sc);
+ setenvironment(sc->envir);
+}
+
+/* Find the slot in ENV under the key HDL. If ALL is given, look in
+ * all environments enclosing ENV. If the lookup fails, and SSLOT is
+ * given, the position where the new slot has to be inserted is stored
+ * at SSLOT. */
+static pointer
+find_slot_spec_in_env(scheme *sc, pointer env, pointer hdl, int all, pointer **sslot)
+{
+ pointer x,y;
+ int location;
+ pointer *sl;
+ int d;
+ assert(is_symbol(hdl));
+
+ for (x = env; x != sc->NIL; x = cdr(x)) {
+ if (is_vector(car(x))) {
+ location = hash_fn(symname(hdl), vector_length(car(x)));
+ sl = vector_elem_slot(car(x), location);
+ } else {
+ sl = &car(x);
+ }
+ for (y = *sl ; y != sc->NIL; sl = &cdr(y), y = *sl) {
+ d = pointercmp(caar(y), hdl);
+ if (d == 0)
+ return car(y); /* Hit. */
+ else if (d > 0)
+ break; /* Miss. */
+ }
+
+ if (x == env && sslot)
+ *sslot = sl; /* Insert here. */
+
+ if (!all)
+ return sc->NIL; /* Miss, and stop looking. */
+ }
+
+ return sc->NIL; /* Not found in any environment. */
+}
+
+#else /* USE_ALIST_ENV */
+
+static INLINE void new_frame_in_env(scheme *sc, pointer old_env)
+{
+ sc->envir = immutable_cons(sc, sc->NIL, old_env);
+ setenvironment(sc->envir);
+}
+
+/* Find the slot in ENV under the key HDL. If ALL is given, look in
+ * all environments enclosing ENV. If the lookup fails, and SSLOT is
+ * given, the position where the new slot has to be inserted is stored
+ * at SSLOT. */
+static pointer
+find_slot_spec_in_env(scheme *sc, pointer env, pointer hdl, int all, pointer **sslot)
+{
+ pointer x,y;
+ pointer *sl;
+ int d;
+ assert(is_symbol(hdl));
+
+ for (x = env; x != sc->NIL; x = cdr(x)) {
+ for (sl = &car(x), y = *sl; y != sc->NIL; sl = &cdr(y), y = *sl) {
+ d = pointercmp(caar(y), hdl);
+ if (d == 0)
+ return car(y); /* Hit. */
+ else if (d > 0)
+ break; /* Miss. */
+ }
+
+ if (x == env && sslot)
+ *sslot = sl; /* Insert here. */
+
+ if (!all)
+ return sc->NIL; /* Miss, and stop looking. */
+ }
+
+ return sc->NIL; /* Not found in any environment. */
+}
+
+#endif /* USE_ALIST_ENV else */
+
+static pointer find_slot_in_env(scheme *sc, pointer env, pointer hdl, int all)
+{
+ return find_slot_spec_in_env(sc, env, hdl, all, NULL);
+}
+
+/* Insert (VARIABLE, VALUE) at SSLOT. SSLOT must be obtained using
+ * find_slot_spec_in_env, and no insertion must be done between
+ * obtaining SSLOT and the call to this function. */
+static INLINE void new_slot_spec_in_env(scheme *sc,
+ pointer variable, pointer value,
+ pointer *sslot)
+{
+#define new_slot_spec_in_env_allocates 2
+ pointer slot;
+ gc_disable(sc, gc_reservations (new_slot_spec_in_env));
+ slot = immutable_cons(sc, variable, value);
+ *sslot = immutable_cons(sc, slot, *sslot);
+ gc_enable(sc);
+}
+
+static INLINE void new_slot_in_env(scheme *sc, pointer variable, pointer value)
+{
+#define new_slot_in_env_allocates new_slot_spec_in_env_allocates
+ pointer slot;
+ pointer *sslot;
+ assert(is_symbol(variable));
+ slot = find_slot_spec_in_env(sc, sc->envir, variable, 0, &sslot);
+ assert(slot == sc->NIL);
+ new_slot_spec_in_env(sc, variable, value, sslot);
+}
+
+static INLINE void set_slot_in_env(scheme *sc, pointer slot, pointer value)
+{
+ (void)sc;
+ cdr(slot) = value;
+}
+
+static INLINE pointer slot_value_in_env(pointer slot)
+{
+ return cdr(slot);
+}
+
+
+/* ========== Evaluation Cycle ========== */
+
+
+static enum scheme_opcodes
+_Error_1(scheme *sc, const char *s, pointer a) {
+ const char *str = s;
+ pointer history;
+#if USE_ERROR_HOOK
+ pointer x;
+ pointer hdl=sc->ERROR_HOOK;
+#endif
+
+#if SHOW_ERROR_LINE
+ char sbuf[STRBUFFSIZE];
+#endif
+
+ history = history_flatten(sc);
+
+#if SHOW_ERROR_LINE
+ /* make sure error is not in REPL */
+ if (((sc->load_stack[sc->file_i].kind & port_file) == 0
+ || sc->load_stack[sc->file_i].rep.stdio.file != stdin)) {
+ pointer tag;
+ const char *fname;
+ int ln;
+
+ if (history != sc->NIL && has_tag(car(history))
+ && (tag = get_tag(sc, car(history)))
+ && is_string(car(tag)) && is_integer(cdr(tag))) {
+ fname = string_value(car(tag));
+ ln = ivalue_unchecked(cdr(tag));
+ } else {
+ fname = string_value(sc->load_stack[sc->file_i].filename);
+ ln = ivalue_unchecked(sc->load_stack[sc->file_i].curr_line);
+ }
+
+ /* should never happen */
+ if(!fname) fname = "<unknown>";
+
+ /* we started from 0 */
+ ln++;
+ snprintf(sbuf, STRBUFFSIZE, "%s:%i: %s", fname, ln, s);
+
+ str = (const char*)sbuf;
+ }
+#endif
+
+#if USE_ERROR_HOOK
+ x=find_slot_in_env(sc,sc->envir,hdl,1);
+ if (x != sc->NIL) {
+ sc->code = cons(sc, cons(sc, sc->QUOTE,
+ cons(sc, history, sc->NIL)),
+ sc->NIL);
+ if(a!=0) {
+ sc->code = cons(sc, cons(sc, sc->QUOTE, cons(sc, a, sc->NIL)),
+ sc->code);
+ } else {
+ sc->code = cons(sc, sc->F, sc->code);
+ }
+ sc->code = cons(sc, mk_string(sc, str), sc->code);
+ setimmutable(car(sc->code));
+ sc->code = cons(sc, slot_value_in_env(x), sc->code);
+ return OP_EVAL;
+ }
+#endif
+
+ if(a!=0) {
+ sc->args = cons(sc, (a), sc->NIL);
+ } else {
+ sc->args = sc->NIL;
+ }
+ sc->args = cons(sc, mk_string(sc, str), sc->args);
+ setimmutable(car(sc->args));
+ return OP_ERR0;
+}
+#define Error_1(sc,s, a) { op = _Error_1(sc,s,a); goto dispatch; }
+#define Error_0(sc,s) { op = _Error_1(sc,s,0); goto dispatch; }
+
+/* Too small to turn into function */
+# define BEGIN do {
+# define END } while (0)
+
+
+
+/* Flags. The interpreter has a flags field. When the interpreter
+ * pushes a frame to the dump stack, it is encoded with the opcode.
+ * Therefore, we do not use the least significant byte. */
+
+/* Masks used to encode and decode opcode and flags. */
+#define S_OP_MASK 0x000000ff
+#define S_FLAG_MASK 0xffffff00
+
+/* Set if the interpreter evaluates an expression in a tail context
+ * (see R5RS, section 3.5). If a function, procedure, or continuation
+ * is invoked while this flag is set, the call is recorded as tail
+ * call in the history buffer. */
+#define S_FLAG_TAIL_CONTEXT 0x00000100
+
+/* Set flag F. */
+#define s_set_flag(sc, f) \
+ BEGIN \
+ (sc)->flags |= S_FLAG_ ## f; \
+ END
+
+/* Clear flag F. */
+#define s_clear_flag(sc, f) \
+ BEGIN \
+ (sc)->flags &= ~ S_FLAG_ ## f; \
+ END
+
+/* Check if flag F is set. */
+#define s_get_flag(sc, f) \
+ !!((sc)->flags & S_FLAG_ ## f)
+
+
+
+/* Bounce back to Eval_Cycle and execute A. */
+#define s_goto(sc, a) { op = (a); goto dispatch; }
+
+#if USE_THREADED_CODE
+
+/* Do not bounce back to Eval_Cycle but execute A by jumping directly
+ * to it. */
+#define s_thread_to(sc, a) \
+ BEGIN \
+ op = (a); \
+ goto a; \
+ END
+
+/* Define a label OP and emit a case statement for OP. For use in the
+ * dispatch function. The slightly peculiar goto that is never
+ * executed avoids warnings about unused labels. */
+#define CASE(OP) case OP: if (0) goto OP; OP
+
+#else /* USE_THREADED_CODE */
+#define s_thread_to(sc, a) s_goto(sc, a)
+#define CASE(OP) case OP
+#endif /* USE_THREADED_CODE */
+
+/* Return to the previous frame on the dump stack, setting the current
+ * value to A. */
+#define s_return(sc, a) s_goto(sc, _s_return(sc, a, 0))
+
+/* Return to the previous frame on the dump stack, setting the current
+ * value to A, and re-enable the garbage collector. */
+#define s_return_enable_gc(sc, a) s_goto(sc, _s_return(sc, a, 1))
+
+static INLINE void dump_stack_reset(scheme *sc)
+{
+ sc->dump = sc->NIL;
+}
+
+static INLINE void dump_stack_initialize(scheme *sc)
+{
+ dump_stack_reset(sc);
+ sc->frame_freelist = sc->NIL;
+}
+
+static void dump_stack_free(scheme *sc)
+{
+ dump_stack_initialize(sc);
+}
+
+const int frame_length = 4;
+
+static pointer
+dump_stack_make_frame(scheme *sc)
+{
+ pointer frame;
+
+ frame = mk_vector(sc, frame_length);
+ if (! sc->no_memory)
+ setframe(frame);
+
+ return frame;
+}
+
+static INLINE pointer *
+frame_slots(pointer frame)
+{
+ return &frame->_object._vector._elements[0];
+}
+
+#define frame_payload vector_length
+
+static pointer
+dump_stack_allocate_frame(scheme *sc)
+{
+ pointer frame = sc->frame_freelist;
+ if (frame == sc->NIL) {
+ if (gc_enabled(sc))
+ frame = dump_stack_make_frame(sc);
+ else
+ gc_reservation_failure(sc);
+ } else
+ sc->frame_freelist = *frame_slots(frame);
+ return frame;
+}
+
+static void
+dump_stack_deallocate_frame(scheme *sc, pointer frame)
+{
+ pointer *p = frame_slots(frame);
+ *p++ = sc->frame_freelist;
+ *p++ = sc->NIL;
+ *p++ = sc->NIL;
+ *p++ = sc->NIL;
+ sc->frame_freelist = frame;
+}
+
+static void
+dump_stack_preallocate_frame(scheme *sc)
+{
+ pointer frame = dump_stack_make_frame(sc);
+ if (! sc->no_memory)
+ dump_stack_deallocate_frame(sc, frame);
+}
+
+static enum scheme_opcodes
+_s_return(scheme *sc, pointer a, int enable_gc) {
+ pointer dump = sc->dump;
+ pointer *p;
+ unsigned long v;
+ enum scheme_opcodes next_op;
+ sc->value = (a);
+ if (enable_gc)
+ gc_enable(sc);
+ if (dump == sc->NIL)
+ return OP_QUIT;
+ v = frame_payload(dump);
+ next_op = (int) (v & S_OP_MASK);
+ sc->flags = v & S_FLAG_MASK;
+ p = frame_slots(dump);
+ sc->args = *p++;
+ sc->envir = *p++;
+ sc->code = *p++;
+ sc->dump = *p++;
+ dump_stack_deallocate_frame(sc, dump);
+ return next_op;
+}
+
+static void s_save(scheme *sc, enum scheme_opcodes op, pointer args, pointer code) {
+#define s_save_allocates 0
+ pointer dump;
+ pointer *p;
+ gc_disable(sc, gc_reservations (s_save));
+ dump = dump_stack_allocate_frame(sc);
+ frame_payload(dump) = (size_t) (sc->flags | (unsigned long) op);
+ p = frame_slots(dump);
+ *p++ = args;
+ *p++ = sc->envir;
+ *p++ = code;
+ *p++ = sc->dump;
+ sc->dump = dump;
+ gc_enable(sc);
+}
+
+static INLINE void dump_stack_mark(scheme *sc)
+{
+ mark(sc->dump);
+ mark(sc->frame_freelist);
+}
+
+
+
+#if USE_HISTORY
+
+static void
+history_free(scheme *sc)
+{
+ sc->free(sc->history.m);
+ sc->history.tailstacks = sc->NIL;
+ sc->history.callstack = sc->NIL;
+}
+
+static pointer
+history_init(scheme *sc, size_t N, size_t M)
+{
+ size_t i;
+ struct history *h = &sc->history;
+
+ h->N = N;
+ h->mask_N = N - 1;
+ h->n = N - 1;
+ assert ((N & h->mask_N) == 0);
+
+ h->M = M;
+ h->mask_M = M - 1;
+ assert ((M & h->mask_M) == 0);
+
+ h->callstack = mk_vector(sc, N);
+ if (h->callstack == sc->sink)
+ goto fail;
+
+ h->tailstacks = mk_vector(sc, N);
+ for (i = 0; i < N; i++) {
+ pointer tailstack = mk_vector(sc, M);
+ if (tailstack == sc->sink)
+ goto fail;
+ set_vector_elem(h->tailstacks, i, tailstack);
+ }
+
+ h->m = sc->malloc(N * sizeof *h->m);
+ if (h->m == NULL)
+ goto fail;
+
+ for (i = 0; i < N; i++)
+ h->m[i] = 0;
+
+ return sc->T;
+
+fail:
+ history_free(sc);
+ return sc->F;
+}
+
+static void
+history_mark(scheme *sc)
+{
+ struct history *h = &sc->history;
+ mark(h->callstack);
+ mark(h->tailstacks);
+}
+
+#define add_mod(a, b, mask) (((a) + (b)) & (mask))
+#define sub_mod(a, b, mask) add_mod(a, (mask) + 1 - (b), mask)
+
+static INLINE void
+tailstack_clear(scheme *sc, pointer v)
+{
+ assert(is_vector(v));
+ /* XXX optimize */
+ fill_vector(v, sc->NIL);
+}
+
+static pointer
+callstack_pop(scheme *sc)
+{
+ struct history *h = &sc->history;
+ size_t n = h->n;
+ pointer item;
+
+ if (h->callstack == sc->NIL)
+ return sc->NIL;
+
+ item = vector_elem(h->callstack, n);
+ /* Clear our frame so that it can be gc'ed and we don't run into it
+ * when walking the history. */
+ set_vector_elem(h->callstack, n, sc->NIL);
+ tailstack_clear(sc, vector_elem(h->tailstacks, n));
+
+ /* Exit from the frame. */
+ h->n = sub_mod(h->n, 1, h->mask_N);
+
+ return item;
+}
+
+static void
+callstack_push(scheme *sc, pointer item)
+{
+ struct history *h = &sc->history;
+ size_t n = h->n;
+
+ if (h->callstack == sc->NIL)
+ return;
+
+ /* Enter a new frame. */
+ n = h->n = add_mod(n, 1, h->mask_N);
+
+ /* Initialize tail stack. */
+ tailstack_clear(sc, vector_elem(h->tailstacks, n));
+ h->m[n] = h->mask_M;
+
+ set_vector_elem(h->callstack, n, item);
+}
+
+static void
+tailstack_push(scheme *sc, pointer item)
+{
+ struct history *h = &sc->history;
+ size_t n = h->n;
+ size_t m = h->m[n];
+
+ if (h->callstack == sc->NIL)
+ return;
+
+ /* Enter a new tail frame. */
+ m = h->m[n] = add_mod(m, 1, h->mask_M);
+ set_vector_elem(vector_elem(h->tailstacks, n), m, item);
+}
+
+static pointer
+tailstack_flatten(scheme *sc, pointer tailstack, size_t i, size_t n,
+ pointer acc)
+{
+ struct history *h = &sc->history;
+ pointer frame;
+
+ assert(i <= h->M);
+ assert(n < h->M);
+
+ if (acc == sc->sink)
+ return sc->sink;
+
+ if (i == 0) {
+ /* We reached the end, but we did not see a unused frame. Signal
+ this using '... . */
+ return cons(sc, mk_symbol(sc, "..."), acc);
+ }
+
+ frame = vector_elem(tailstack, n);
+ if (frame == sc->NIL) {
+ /* A unused frame. We reached the end of the history. */
+ return acc;
+ }
+
+ /* Add us. */
+ acc = cons(sc, frame, acc);
+
+ return tailstack_flatten(sc, tailstack, i - 1, sub_mod(n, 1, h->mask_M),
+ acc);
+}
+
+static pointer
+callstack_flatten(scheme *sc, size_t i, size_t n, pointer acc)
+{
+ struct history *h = &sc->history;
+ pointer frame;
+
+ assert(i <= h->N);
+ assert(n < h->N);
+
+ if (acc == sc->sink)
+ return sc->sink;
+
+ if (i == 0) {
+ /* We reached the end, but we did not see a unused frame. Signal
+ this using '... . */
+ return cons(sc, mk_symbol(sc, "..."), acc);
+ }
+
+ frame = vector_elem(h->callstack, n);
+ if (frame == sc->NIL) {
+ /* A unused frame. We reached the end of the history. */
+ return acc;
+ }
+
+ /* First, emit the tail calls. */
+ acc = tailstack_flatten(sc, vector_elem(h->tailstacks, n), h->M, h->m[n],
+ acc);
+
+ /* Then us. */
+ acc = cons(sc, frame, acc);
+
+ return callstack_flatten(sc, i - 1, sub_mod(n, 1, h->mask_N), acc);
+}
+
+static pointer
+history_flatten(scheme *sc)
+{
+ struct history *h = &sc->history;
+ pointer history;
+
+ if (h->callstack == sc->NIL)
+ return sc->NIL;
+
+ history = callstack_flatten(sc, h->N, h->n, sc->NIL);
+ if (history == sc->sink)
+ return sc->sink;
+
+ return reverse_in_place(sc, sc->NIL, history);
+}
+
+#undef add_mod
+#undef sub_mod
+
+#else /* USE_HISTORY */
+
+#define history_init(SC, A, B) (void) 0
+#define history_free(SC) (void) 0
+#define callstack_pop(SC) (void) 0
+#define callstack_push(SC, X) (void) 0
+#define tailstack_push(SC, X) (void) 0
+
+#endif /* USE_HISTORY */
+
+
+
+#if USE_PLIST
+static pointer
+get_property(scheme *sc, pointer obj, pointer key)
+{
+ pointer x;
+
+ assert (is_symbol(obj));
+ assert (is_symbol(key));
+
+ for (x = symprop(obj); x != sc->NIL; x = cdr(x)) {
+ if (caar(x) == key)
+ break;
+ }
+
+ if (x != sc->NIL)
+ return cdar(x);
+
+ return sc->NIL;
+}
+
+static pointer
+set_property(scheme *sc, pointer obj, pointer key, pointer value)
+{
+#define set_property_allocates 2
+ pointer x;
+
+ assert (is_symbol(obj));
+ assert (is_symbol(key));
+
+ for (x = symprop(obj); x != sc->NIL; x = cdr(x)) {
+ if (caar(x) == key)
+ break;
+ }
+
+ if (x != sc->NIL)
+ cdar(x) = value;
+ else {
+ gc_disable(sc, gc_reservations(set_property));
+ symprop(obj) = cons(sc, cons(sc, key, value), symprop(obj));
+ gc_enable(sc);
+ }
+
+ return sc->T;
+}
+#endif
+
+
+
+static int is_list(scheme *sc, pointer a)
+{ return list_length(sc,a) >= 0; }
+
+/* Result is:
+ proper list: length
+ circular list: -1
+ not even a pair: -2
+ dotted list: -2 minus length before dot
+*/
+int list_length(scheme *sc, pointer a) {
+ int i=0;
+ pointer slow, fast;
+
+ slow = fast = a;
+ while (1)
+ {
+ if (fast == sc->NIL)
+ return i;
+ if (!is_pair(fast))
+ return -2 - i;
+ fast = cdr(fast);
+ ++i;
+ if (fast == sc->NIL)
+ return i;
+ if (!is_pair(fast))
+ return -2 - i;
+ ++i;
+ fast = cdr(fast);
+
+ /* Safe because we would have already returned if `fast'
+ encountered a non-pair. */
+ slow = cdr(slow);
+ if (fast == slow)
+ {
+ /* the fast pointer has looped back around and caught up
+ with the slow pointer, hence the structure is circular,
+ not of finite length, and therefore not a list */
+ return -1;
+ }
+ }
+}
+
+
+
+#if GPGRT_GCC_VERSION >= 80000
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
+#endif
+
+#define s_retbool(tf) s_return(sc,(tf) ? sc->T : sc->F)
+
+/* kernel of this interpreter */
+static void
+Eval_Cycle(scheme *sc, enum scheme_opcodes op) {
+ for (;;) {
+ pointer x, y;
+ pointer callsite;
+ num v;
+#if USE_MATH
+ double dd;
+#endif
+ int (*comp_func)(num, num) = NULL;
+ const struct op_code_info *pcd;
+
+ dispatch:
+ pcd = &dispatch_table[op];
+ if (pcd->name[0] != 0) { /* if built-in function, check arguments */
+ char msg[STRBUFFSIZE];
+ if (! check_arguments (sc, pcd, msg, sizeof msg)) {
+ s_goto(sc, _Error_1(sc, msg, 0));
+ }
+ }
+
+ if(sc->no_memory) {
+ fprintf(stderr,"No memory!\n");
+ exit(1);
+ }
+ ok_to_freely_gc(sc);
+
+ switch (op) {
+ CASE(OP_LOAD): /* load */
+ if(file_interactive(sc)) {
+ fprintf(sc->outport->_object._port->rep.stdio.file,
+ "Loading %s\n", strvalue(car(sc->args)));
+ }
+ if (!file_push(sc, car(sc->args))) {
+ Error_1(sc,"unable to open", car(sc->args));
+ }
+ else
+ {
+ sc->args = mk_integer(sc,sc->file_i);
+ s_thread_to(sc,OP_T0LVL);
+ }
+
+ CASE(OP_T0LVL): /* top level */
+ /* If we reached the end of file, this loop is done. */
+ if(sc->loadport->_object._port->kind & port_saw_EOF)
+ {
+ if(sc->file_i == 0)
+ {
+ sc->args=sc->NIL;
+ sc->nesting = sc->nesting_stack[0];
+ s_thread_to(sc,OP_QUIT);
+ }
+ else
+ {
+ file_pop(sc);
+ s_return(sc,sc->value);
+ }
+ /* NOTREACHED */
+ }
+
+ /* If interactive, be nice to user. */
+ if(file_interactive(sc))
+ {
+ sc->envir = sc->global_env;
+ dump_stack_reset(sc);
+ putstr(sc,"\n");
+ putstr(sc,prompt);
+ }
+
+ /* Set up another iteration of REPL */
+ sc->nesting=0;
+ sc->save_inport=sc->inport;
+ sc->inport = sc->loadport;
+ s_save(sc,OP_T0LVL, sc->NIL, sc->NIL);
+ s_save(sc,OP_VALUEPRINT, sc->NIL, sc->NIL);
+ s_save(sc,OP_T1LVL, sc->NIL, sc->NIL);
+ s_thread_to(sc,OP_READ_INTERNAL);
+
+ CASE(OP_T1LVL): /* top level */
+ sc->code = sc->value;
+ sc->inport=sc->save_inport;
+ s_thread_to(sc,OP_EVAL);
+
+ CASE(OP_READ_INTERNAL): /* internal read */
+ sc->tok = token(sc);
+ if(sc->tok==TOK_EOF)
+ { s_return(sc,sc->EOF_OBJ); }
+ s_thread_to(sc,OP_RDSEXPR);
+
+ CASE(OP_GENSYM):
+ s_return(sc, gensym(sc));
+
+ CASE(OP_VALUEPRINT): /* print evaluation result */
+ /* OP_VALUEPRINT is always pushed, because when changing from
+ non-interactive to interactive mode, it needs to be
+ already on the stack */
+ if(sc->tracing) {
+ putstr(sc,"\nGives: ");
+ }
+ if(file_interactive(sc)) {
+ sc->print_flag = 1;
+ sc->args = sc->value;
+ s_thread_to(sc,OP_P0LIST);
+ } else {
+ s_return(sc,sc->value);
+ }
+
+ CASE(OP_EVAL): /* main part of evaluation */
+#if USE_TRACING
+ if(sc->tracing) {
+ /*s_save(sc,OP_VALUEPRINT,sc->NIL,sc->NIL);*/
+ s_save(sc,OP_REAL_EVAL,sc->args,sc->code);
+ sc->args=sc->code;
+ putstr(sc,"\nEval: ");
+ s_thread_to(sc,OP_P0LIST);
+ }
+ /* fall through */
+ CASE(OP_REAL_EVAL):
+#endif
+ if (is_symbol(sc->code)) { /* symbol */
+ x=find_slot_in_env(sc,sc->envir,sc->code,1);
+ if (x != sc->NIL) {
+ s_return(sc,slot_value_in_env(x));
+ } else {
+ Error_1(sc, "eval: unbound variable", sc->code);
+ }
+ } else if (is_pair(sc->code)) {
+ if (is_syntax(x = car(sc->code))) { /* SYNTAX */
+ sc->code = cdr(sc->code);
+ s_goto(sc, syntaxnum(sc, x));
+ } else {/* first, eval top element and eval arguments */
+ s_save(sc,OP_E0ARGS, sc->NIL, sc->code);
+ /* If no macros => s_save(sc,OP_E1ARGS, sc->NIL, cdr(sc->code));*/
+ sc->code = car(sc->code);
+ s_clear_flag(sc, TAIL_CONTEXT);
+ s_thread_to(sc,OP_EVAL);
+ }
+ } else {
+ s_return(sc,sc->code);
+ }
+
+ CASE(OP_E0ARGS): /* eval arguments */
+ if (is_macro(sc->value)) { /* macro expansion */
+ gc_disable(sc, 1 + gc_reservations (s_save));
+ s_save(sc,OP_DOMACRO, sc->NIL, sc->NIL);
+ sc->args = cons(sc,sc->code, sc->NIL);
+ gc_enable(sc);
+ sc->code = sc->value;
+ s_clear_flag(sc, TAIL_CONTEXT);
+ s_thread_to(sc,OP_APPLY);
+ } else {
+ gc_disable(sc, 1);
+ sc->args = cons(sc, sc->code, sc->NIL);
+ gc_enable(sc);
+ sc->code = cdr(sc->code);
+ s_thread_to(sc,OP_E1ARGS);
+ }
+
+ CASE(OP_E1ARGS): /* eval arguments */
+ gc_disable(sc, 1);
+ sc->args = cons(sc, sc->value, sc->args);
+ gc_enable(sc);
+ if (is_pair(sc->code)) { /* continue */
+ s_save(sc,OP_E1ARGS, sc->args, cdr(sc->code));
+ sc->code = car(sc->code);
+ sc->args = sc->NIL;
+ s_clear_flag(sc, TAIL_CONTEXT);
+ s_thread_to(sc,OP_EVAL);
+ } else { /* end */
+ sc->args = reverse_in_place(sc, sc->NIL, sc->args);
+ s_thread_to(sc,OP_APPLY_CODE);
+ }
+
+#if USE_TRACING
+ CASE(OP_TRACING): {
+ int tr=sc->tracing;
+ sc->tracing=ivalue(car(sc->args));
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_integer(sc, tr));
+ }
+#endif
+
+#if USE_HISTORY
+ CASE(OP_CALLSTACK_POP): /* pop the call stack */
+ callstack_pop(sc);
+ s_return(sc, sc->value);
+#endif
+
+ CASE(OP_APPLY_CODE): /* apply 'cadr(args)' to 'cddr(args)',
+ * record in the history as invoked from
+ * 'car(args)' */
+ free_cons(sc, sc->args, &callsite, &sc->args);
+ sc->code = car(sc->args);
+ sc->args = cdr(sc->args);
+ /* Fallthrough. */
+
+ CASE(OP_APPLY): /* apply 'code' to 'args' */
+#if USE_TRACING
+ if(sc->tracing) {
+ s_save(sc,OP_REAL_APPLY,sc->args,sc->code);
+ sc->print_flag = 1;
+ /* sc->args=cons(sc,sc->code,sc->args);*/
+ putstr(sc,"\nApply to: ");
+ s_thread_to(sc,OP_P0LIST);
+ }
+ /* fall through */
+ CASE(OP_REAL_APPLY):
+#endif
+#if USE_HISTORY
+ if (op != OP_APPLY_CODE)
+ callsite = sc->code;
+ if (s_get_flag(sc, TAIL_CONTEXT)) {
+ /* We are evaluating a tail call. */
+ tailstack_push(sc, callsite);
+ } else {
+ callstack_push(sc, callsite);
+ s_save(sc, OP_CALLSTACK_POP, sc->NIL, sc->NIL);
+ }
+#endif
+
+ if (is_proc(sc->code)) {
+ s_goto(sc,procnum(sc->code)); /* PROCEDURE */
+ } else if (is_foreign(sc->code))
+ {
+ /* Keep nested calls from GC'ing the arglist */
+ push_recent_alloc(sc,sc->args,sc->NIL);
+ x=sc->code->_object._ff(sc,sc->args);
+ s_return(sc,x);
+ } else if (is_closure(sc->code) || is_macro(sc->code)
+ || is_promise(sc->code)) { /* CLOSURE */
+ /* Should not accept promise */
+ /* make environment */
+ new_frame_in_env(sc, closure_env(sc->code));
+ for (x = car(closure_code(sc->code)), y = sc->args;
+ is_pair(x); x = cdr(x), y = cdr(y)) {
+ if (y == sc->NIL) {
+ Error_1(sc, "not enough arguments, missing", x);
+ } else if (is_symbol(car(x))) {
+ new_slot_in_env(sc, car(x), car(y));
+ } else {
+ Error_1(sc, "syntax error in closure: not a symbol", car(x));
+ }
+ }
+
+ if (x == sc->NIL) {
+ if (y != sc->NIL) {
+ Error_0(sc, "too many arguments");
+ }
+ } else if (is_symbol(x))
+ new_slot_in_env(sc, x, y);
+ else {
+ Error_1(sc, "syntax error in closure: not a symbol", x);
+ }
+ sc->code = cdr(closure_code(sc->code));
+ sc->args = sc->NIL;
+ s_set_flag(sc, TAIL_CONTEXT);
+ s_thread_to(sc,OP_BEGIN);
+ } else if (is_continuation(sc->code)) { /* CONTINUATION */
+ sc->dump = cont_dump(sc->code);
+ s_return(sc,sc->args != sc->NIL ? car(sc->args) : sc->NIL);
+ } else {
+ Error_1(sc,"illegal function",sc->code);
+ }
+
+ CASE(OP_DOMACRO): /* do macro */
+ sc->code = sc->value;
+ s_thread_to(sc,OP_EVAL);
+
+#if USE_COMPILE_HOOK
+ CASE(OP_LAMBDA): /* lambda */
+ /* If the hook is defined, apply it to sc->code, otherwise
+ set sc->value fall through */
+ {
+ pointer f=find_slot_in_env(sc,sc->envir,sc->COMPILE_HOOK,1);
+ if(f==sc->NIL) {
+ sc->value = sc->code;
+ /* Fallthru */
+ } else {
+ gc_disable(sc, 1 + gc_reservations (s_save));
+ s_save(sc,OP_LAMBDA1,sc->args,sc->code);
+ sc->args=cons(sc,sc->code,sc->NIL);
+ gc_enable(sc);
+ sc->code=slot_value_in_env(f);
+ s_thread_to(sc,OP_APPLY);
+ }
+ }
+ /* Fallthrough. */
+#else
+ CASE(OP_LAMBDA): /* lambda */
+ sc->value = sc->code;
+ /* Fallthrough. */
+#endif
+
+ CASE(OP_LAMBDA1):
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_closure(sc, sc->value, sc->envir));
+
+
+ CASE(OP_MKCLOSURE): /* make-closure */
+ x=car(sc->args);
+ if(car(x)==sc->LAMBDA) {
+ x=cdr(x);
+ }
+ if(cdr(sc->args)==sc->NIL) {
+ y=sc->envir;
+ } else {
+ y=cadr(sc->args);
+ }
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_closure(sc, x, y));
+
+ CASE(OP_QUOTE): /* quote */
+ s_return(sc,car(sc->code));
+
+ CASE(OP_DEF0): /* define */
+ if(is_immutable(car(sc->code)))
+ Error_1(sc,"define: unable to alter immutable", car(sc->code));
+
+ if (is_pair(car(sc->code))) {
+ x = caar(sc->code);
+ gc_disable(sc, 2);
+ sc->code = cons(sc, sc->LAMBDA, cons(sc, cdar(sc->code), cdr(sc->code)));
+ gc_enable(sc);
+ } else {
+ x = car(sc->code);
+ sc->code = cadr(sc->code);
+ }
+ if (!is_symbol(x)) {
+ Error_0(sc,"variable is not a symbol");
+ }
+ s_save(sc,OP_DEF1, sc->NIL, x);
+ s_thread_to(sc,OP_EVAL);
+
+ CASE(OP_DEF1): { /* define */
+ pointer *sslot;
+ x = find_slot_spec_in_env(sc, sc->envir, sc->code, 0, &sslot);
+ if (x != sc->NIL) {
+ set_slot_in_env(sc, x, sc->value);
+ } else {
+ new_slot_spec_in_env(sc, sc->code, sc->value, sslot);
+ }
+ s_return(sc,sc->code);
+ }
+
+ CASE(OP_DEFP): /* defined? */
+ x=sc->envir;
+ if(cdr(sc->args)!=sc->NIL) {
+ x=cadr(sc->args);
+ }
+ s_retbool(find_slot_in_env(sc,x,car(sc->args),1)!=sc->NIL);
+
+ CASE(OP_SET0): /* set! */
+ if(is_immutable(car(sc->code)))
+ Error_1(sc,"set!: unable to alter immutable variable",car(sc->code));
+ s_save(sc,OP_SET1, sc->NIL, car(sc->code));
+ sc->code = cadr(sc->code);
+ s_thread_to(sc,OP_EVAL);
+
+ CASE(OP_SET1): /* set! */
+ y=find_slot_in_env(sc,sc->envir,sc->code,1);
+ if (y != sc->NIL) {
+ set_slot_in_env(sc, y, sc->value);
+ s_return(sc,sc->value);
+ } else {
+ Error_1(sc, "set!: unbound variable", sc->code);
+ }
+
+
+ CASE(OP_BEGIN): /* begin */
+ {
+ int last;
+
+ if (!is_pair(sc->code)) {
+ s_return(sc,sc->code);
+ }
+
+ last = cdr(sc->code) == sc->NIL;
+ if (!last) {
+ s_save(sc,OP_BEGIN, sc->NIL, cdr(sc->code));
+ }
+ sc->code = car(sc->code);
+ if (! last)
+ /* This is not the end of the list. This is not a tail
+ * position. */
+ s_clear_flag(sc, TAIL_CONTEXT);
+ s_thread_to(sc,OP_EVAL);
+ }
+
+ CASE(OP_IF0): /* if */
+ s_save(sc,OP_IF1, sc->NIL, cdr(sc->code));
+ sc->code = car(sc->code);
+ s_clear_flag(sc, TAIL_CONTEXT);
+ s_thread_to(sc,OP_EVAL);
+
+ CASE(OP_IF1): /* if */
+ if (is_true(sc->value))
+ sc->code = car(sc->code);
+ else
+ sc->code = cadr(sc->code); /* (if #f 1) ==> () because
+ * car(sc->NIL) = sc->NIL */
+ s_thread_to(sc,OP_EVAL);
+
+ CASE(OP_LET0): /* let */
+ sc->args = sc->NIL;
+ sc->value = sc->code;
+ sc->code = is_symbol(car(sc->code)) ? cadr(sc->code) : car(sc->code);
+ s_thread_to(sc,OP_LET1);
+
+ CASE(OP_LET1): /* let (calculate parameters) */
+ gc_disable(sc, 1 + (is_pair(sc->code) ? gc_reservations (s_save) : 0));
+ sc->args = cons(sc, sc->value, sc->args);
+ if (is_pair(sc->code)) { /* continue */
+ if (!is_pair(car(sc->code)) || !is_pair(cdar(sc->code))) {
+ gc_enable(sc);
+ Error_1(sc, "Bad syntax of binding spec in let",
+ car(sc->code));
+ }
+ s_save(sc,OP_LET1, sc->args, cdr(sc->code));
+ gc_enable(sc);
+ sc->code = cadar(sc->code);
+ sc->args = sc->NIL;
+ s_clear_flag(sc, TAIL_CONTEXT);
+ s_thread_to(sc,OP_EVAL);
+ } else { /* end */
+ gc_enable(sc);
+ sc->args = reverse_in_place(sc, sc->NIL, sc->args);
+ sc->code = car(sc->args);
+ sc->args = cdr(sc->args);
+ s_thread_to(sc,OP_LET2);
+ }
+
+ CASE(OP_LET2): /* let */
+ new_frame_in_env(sc, sc->envir);
+ for (x = is_symbol(car(sc->code)) ? cadr(sc->code) : car(sc->code), y = sc->args;
+ y != sc->NIL; x = cdr(x), y = cdr(y)) {
+ new_slot_in_env(sc, caar(x), car(y));
+ }
+ if (is_symbol(car(sc->code))) { /* named let */
+ for (x = cadr(sc->code), sc->args = sc->NIL; x != sc->NIL; x = cdr(x)) {
+ if (!is_pair(x))
+ Error_1(sc, "Bad syntax of binding in let", x);
+ if (!is_list(sc, car(x)))
+ Error_1(sc, "Bad syntax of binding in let", car(x));
+ gc_disable(sc, 1);
+ sc->args = cons(sc, caar(x), sc->args);
+ gc_enable(sc);
+ }
+ gc_disable(sc, 2 + gc_reservations (new_slot_in_env));
+ x = mk_closure(sc, cons(sc, reverse_in_place(sc, sc->NIL, sc->args), cddr(sc->code)), sc->envir);
+ new_slot_in_env(sc, car(sc->code), x);
+ gc_enable(sc);
+ sc->code = cddr(sc->code);
+ sc->args = sc->NIL;
+ } else {
+ sc->code = cdr(sc->code);
+ sc->args = sc->NIL;
+ }
+ s_thread_to(sc,OP_BEGIN);
+
+ CASE(OP_LET0AST): /* let* */
+ if (car(sc->code) == sc->NIL) {
+ new_frame_in_env(sc, sc->envir);
+ sc->code = cdr(sc->code);
+ s_thread_to(sc,OP_BEGIN);
+ }
+ if(!is_pair(car(sc->code)) || !is_pair(caar(sc->code)) || !is_pair(cdaar(sc->code))) {
+ Error_1(sc, "Bad syntax of binding spec in let*", car(sc->code));
+ }
+ s_save(sc,OP_LET1AST, cdr(sc->code), car(sc->code));
+ sc->code = cadaar(sc->code);
+ s_clear_flag(sc, TAIL_CONTEXT);
+ s_thread_to(sc,OP_EVAL);
+
+ CASE(OP_LET1AST): /* let* (make new frame) */
+ new_frame_in_env(sc, sc->envir);
+ s_thread_to(sc,OP_LET2AST);
+
+ CASE(OP_LET2AST): /* let* (calculate parameters) */
+ new_slot_in_env(sc, caar(sc->code), sc->value);
+ sc->code = cdr(sc->code);
+ if (is_pair(sc->code)) { /* continue */
+ s_save(sc,OP_LET2AST, sc->args, sc->code);
+ sc->code = cadar(sc->code);
+ sc->args = sc->NIL;
+ s_clear_flag(sc, TAIL_CONTEXT);
+ s_thread_to(sc,OP_EVAL);
+ } else { /* end */
+ sc->code = sc->args;
+ sc->args = sc->NIL;
+ s_thread_to(sc,OP_BEGIN);
+ }
+
+ CASE(OP_LET0REC): /* letrec */
+ new_frame_in_env(sc, sc->envir);
+ sc->args = sc->NIL;
+ sc->value = sc->code;
+ sc->code = car(sc->code);
+ s_thread_to(sc,OP_LET1REC);
+
+ CASE(OP_LET1REC): /* letrec (calculate parameters) */
+ gc_disable(sc, 1);
+ sc->args = cons(sc, sc->value, sc->args);
+ gc_enable(sc);
+ if (is_pair(sc->code)) { /* continue */
+ if (!is_pair(car(sc->code)) || !is_pair(cdar(sc->code))) {
+ Error_1(sc, "Bad syntax of binding spec in letrec",
+ car(sc->code));
+ }
+ s_save(sc,OP_LET1REC, sc->args, cdr(sc->code));
+ sc->code = cadar(sc->code);
+ sc->args = sc->NIL;
+ s_clear_flag(sc, TAIL_CONTEXT);
+ s_thread_to(sc,OP_EVAL);
+ } else { /* end */
+ sc->args = reverse_in_place(sc, sc->NIL, sc->args);
+ sc->code = car(sc->args);
+ sc->args = cdr(sc->args);
+ s_thread_to(sc,OP_LET2REC);
+ }
+
+ CASE(OP_LET2REC): /* letrec */
+ for (x = car(sc->code), y = sc->args; y != sc->NIL; x = cdr(x), y = cdr(y)) {
+ new_slot_in_env(sc, caar(x), car(y));
+ }
+ sc->code = cdr(sc->code);
+ sc->args = sc->NIL;
+ s_thread_to(sc,OP_BEGIN);
+
+ CASE(OP_COND0): /* cond */
+ if (!is_pair(sc->code)) {
+ Error_0(sc,"syntax error in cond");
+ }
+ s_save(sc,OP_COND1, sc->NIL, sc->code);
+ sc->code = caar(sc->code);
+ s_clear_flag(sc, TAIL_CONTEXT);
+ s_thread_to(sc,OP_EVAL);
+
+ CASE(OP_COND1): /* cond */
+ if (is_true(sc->value)) {
+ if ((sc->code = cdar(sc->code)) == sc->NIL) {
+ s_return(sc,sc->value);
+ }
+ if(!sc->code || car(sc->code)==sc->FEED_TO) {
+ if(!is_pair(cdr(sc->code))) {
+ Error_0(sc,"syntax error in cond");
+ }
+ gc_disable(sc, 4);
+ x=cons(sc, sc->QUOTE, cons(sc, sc->value, sc->NIL));
+ sc->code=cons(sc,cadr(sc->code),cons(sc,x,sc->NIL));
+ gc_enable(sc);
+ s_thread_to(sc,OP_EVAL);
+ }
+ s_thread_to(sc,OP_BEGIN);
+ } else {
+ if ((sc->code = cdr(sc->code)) == sc->NIL) {
+ s_return(sc,sc->NIL);
+ } else {
+ s_save(sc,OP_COND1, sc->NIL, sc->code);
+ sc->code = caar(sc->code);
+ s_clear_flag(sc, TAIL_CONTEXT);
+ s_thread_to(sc,OP_EVAL);
+ }
+ }
+
+ CASE(OP_DELAY): /* delay */
+ gc_disable(sc, 2);
+ x = mk_closure(sc, cons(sc, sc->NIL, sc->code), sc->envir);
+ typeflag(x)=T_PROMISE;
+ s_return_enable_gc(sc,x);
+
+ CASE(OP_AND0): /* and */
+ if (sc->code == sc->NIL) {
+ s_return(sc,sc->T);
+ }
+ s_save(sc,OP_AND1, sc->NIL, cdr(sc->code));
+ if (cdr(sc->code) != sc->NIL)
+ s_clear_flag(sc, TAIL_CONTEXT);
+ sc->code = car(sc->code);
+ s_thread_to(sc,OP_EVAL);
+
+ CASE(OP_AND1): /* and */
+ if (is_false(sc->value)) {
+ s_return(sc,sc->value);
+ } else if (sc->code == sc->NIL) {
+ s_return(sc,sc->value);
+ } else {
+ s_save(sc,OP_AND1, sc->NIL, cdr(sc->code));
+ if (cdr(sc->code) != sc->NIL)
+ s_clear_flag(sc, TAIL_CONTEXT);
+ sc->code = car(sc->code);
+ s_thread_to(sc,OP_EVAL);
+ }
+
+ CASE(OP_OR0): /* or */
+ if (sc->code == sc->NIL) {
+ s_return(sc,sc->F);
+ }
+ s_save(sc,OP_OR1, sc->NIL, cdr(sc->code));
+ if (cdr(sc->code) != sc->NIL)
+ s_clear_flag(sc, TAIL_CONTEXT);
+ sc->code = car(sc->code);
+ s_thread_to(sc,OP_EVAL);
+
+ CASE(OP_OR1): /* or */
+ if (is_true(sc->value)) {
+ s_return(sc,sc->value);
+ } else if (sc->code == sc->NIL) {
+ s_return(sc,sc->value);
+ } else {
+ s_save(sc,OP_OR1, sc->NIL, cdr(sc->code));
+ if (cdr(sc->code) != sc->NIL)
+ s_clear_flag(sc, TAIL_CONTEXT);
+ sc->code = car(sc->code);
+ s_thread_to(sc,OP_EVAL);
+ }
+
+ CASE(OP_C0STREAM): /* cons-stream */
+ s_save(sc,OP_C1STREAM, sc->NIL, cdr(sc->code));
+ sc->code = car(sc->code);
+ s_thread_to(sc,OP_EVAL);
+
+ CASE(OP_C1STREAM): /* cons-stream */
+ sc->args = sc->value; /* save sc->value to register sc->args for gc */
+ gc_disable(sc, 3);
+ x = mk_closure(sc, cons(sc, sc->NIL, sc->code), sc->envir);
+ typeflag(x)=T_PROMISE;
+ s_return_enable_gc(sc, cons(sc, sc->args, x));
+
+ CASE(OP_MACRO0): /* macro */
+ if (is_pair(car(sc->code))) {
+ x = caar(sc->code);
+ gc_disable(sc, 2);
+ sc->code = cons(sc, sc->LAMBDA, cons(sc, cdar(sc->code), cdr(sc->code)));
+ gc_enable(sc);
+ } else {
+ x = car(sc->code);
+ sc->code = cadr(sc->code);
+ }
+ if (!is_symbol(x)) {
+ Error_0(sc,"variable is not a symbol");
+ }
+ s_save(sc,OP_MACRO1, sc->NIL, x);
+ s_thread_to(sc,OP_EVAL);
+
+ CASE(OP_MACRO1): { /* macro */
+ pointer *sslot;
+ typeflag(sc->value) = T_MACRO;
+ x = find_slot_spec_in_env(sc, sc->envir, sc->code, 0, &sslot);
+ if (x != sc->NIL) {
+ set_slot_in_env(sc, x, sc->value);
+ } else {
+ new_slot_spec_in_env(sc, sc->code, sc->value, sslot);
+ }
+ s_return(sc,sc->code);
+ }
+
+ CASE(OP_CASE0): /* case */
+ s_save(sc,OP_CASE1, sc->NIL, cdr(sc->code));
+ sc->code = car(sc->code);
+ s_clear_flag(sc, TAIL_CONTEXT);
+ s_thread_to(sc,OP_EVAL);
+
+ CASE(OP_CASE1): /* case */
+ for (x = sc->code; x != sc->NIL; x = cdr(x)) {
+ if (!is_pair(y = caar(x))) {
+ break;
+ }
+ for ( ; y != sc->NIL; y = cdr(y)) {
+ if (eqv(car(y), sc->value)) {
+ break;
+ }
+ }
+ if (y != sc->NIL) {
+ break;
+ }
+ }
+ if (x != sc->NIL) {
+ if (is_pair(caar(x))) {
+ sc->code = cdar(x);
+ s_thread_to(sc,OP_BEGIN);
+ } else {/* else */
+ s_save(sc,OP_CASE2, sc->NIL, cdar(x));
+ sc->code = caar(x);
+ s_thread_to(sc,OP_EVAL);
+ }
+ } else {
+ s_return(sc,sc->NIL);
+ }
+
+ CASE(OP_CASE2): /* case */
+ if (is_true(sc->value)) {
+ s_thread_to(sc,OP_BEGIN);
+ } else {
+ s_return(sc,sc->NIL);
+ }
+
+ CASE(OP_PAPPLY): /* apply */
+ sc->code = car(sc->args);
+ sc->args = list_star(sc,cdr(sc->args));
+ /*sc->args = cadr(sc->args);*/
+ s_thread_to(sc,OP_APPLY);
+
+ CASE(OP_PEVAL): /* eval */
+ if(cdr(sc->args)!=sc->NIL) {
+ sc->envir=cadr(sc->args);
+ }
+ sc->code = car(sc->args);
+ s_thread_to(sc,OP_EVAL);
+
+ CASE(OP_CONTINUATION): /* call-with-current-continuation */
+ sc->code = car(sc->args);
+ gc_disable(sc, 2);
+ sc->args = cons(sc, mk_continuation(sc, sc->dump), sc->NIL);
+ gc_enable(sc);
+ s_thread_to(sc,OP_APPLY);
+
+#if USE_MATH
+ CASE(OP_INEX2EX): /* inexact->exact */
+ x=car(sc->args);
+ if(num_is_integer(x)) {
+ s_return(sc,x);
+ } else if(modf(rvalue_unchecked(x),&dd)==0.0) {
+ s_return(sc,mk_integer(sc,ivalue(x)));
+ } else {
+ Error_1(sc, "inexact->exact: not integral", x);
+ }
+
+ CASE(OP_EXP):
+ x=car(sc->args);
+ s_return(sc, mk_real(sc, exp(rvalue(x))));
+
+ CASE(OP_LOG):
+ x=car(sc->args);
+ s_return(sc, mk_real(sc, log(rvalue(x))));
+
+ CASE(OP_SIN):
+ x=car(sc->args);
+ s_return(sc, mk_real(sc, sin(rvalue(x))));
+
+ CASE(OP_COS):
+ x=car(sc->args);
+ s_return(sc, mk_real(sc, cos(rvalue(x))));
+
+ CASE(OP_TAN):
+ x=car(sc->args);
+ s_return(sc, mk_real(sc, tan(rvalue(x))));
+
+ CASE(OP_ASIN):
+ x=car(sc->args);
+ s_return(sc, mk_real(sc, asin(rvalue(x))));
+
+ CASE(OP_ACOS):
+ x=car(sc->args);
+ s_return(sc, mk_real(sc, acos(rvalue(x))));
+
+ CASE(OP_ATAN):
+ x=car(sc->args);
+ if(cdr(sc->args)==sc->NIL) {
+ s_return(sc, mk_real(sc, atan(rvalue(x))));
+ } else {
+ pointer y=cadr(sc->args);
+ s_return(sc, mk_real(sc, atan2(rvalue(x),rvalue(y))));
+ }
+
+ CASE(OP_SQRT):
+ x=car(sc->args);
+ s_return(sc, mk_real(sc, sqrt(rvalue(x))));
+
+ CASE(OP_EXPT): {
+ double result;
+ int real_result=1;
+ pointer y=cadr(sc->args);
+ x=car(sc->args);
+ if (num_is_integer(x) && num_is_integer(y))
+ real_result=0;
+ /* This 'if' is an R5RS compatibility fix. */
+ /* NOTE: Remove this 'if' fix for R6RS. */
+ if (rvalue(x) == 0 && rvalue(y) < 0) {
+ result = 0.0;
+ } else {
+ result = pow(rvalue(x),rvalue(y));
+ }
+ /* Before returning integer result make sure we can. */
+ /* If the test fails, result is too big for integer. */
+ if (!real_result)
+ {
+ long result_as_long = (long)result;
+ if (result != (double)result_as_long)
+ real_result = 1;
+ }
+ if (real_result) {
+ s_return(sc, mk_real(sc, result));
+ } else {
+ s_return(sc, mk_integer(sc, result));
+ }
+ }
+
+ CASE(OP_FLOOR):
+ x=car(sc->args);
+ s_return(sc, mk_real(sc, floor(rvalue(x))));
+
+ CASE(OP_CEILING):
+ x=car(sc->args);
+ s_return(sc, mk_real(sc, ceil(rvalue(x))));
+
+ CASE(OP_TRUNCATE ): {
+ double rvalue_of_x ;
+ x=car(sc->args);
+ rvalue_of_x = rvalue(x) ;
+ if (rvalue_of_x > 0) {
+ s_return(sc, mk_real(sc, floor(rvalue_of_x)));
+ } else {
+ s_return(sc, mk_real(sc, ceil(rvalue_of_x)));
+ }
+ }
+
+ CASE(OP_ROUND):
+ x=car(sc->args);
+ if (num_is_integer(x))
+ s_return(sc, x);
+ s_return(sc, mk_real(sc, round_per_R5RS(rvalue(x))));
+#endif
+
+ CASE(OP_ADD): /* + */
+ v=num_zero;
+ for (x = sc->args; x != sc->NIL; x = cdr(x)) {
+ v=num_add(v,nvalue(car(x)));
+ }
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_number(sc, v));
+
+ CASE(OP_MUL): /* * */
+ v=num_one;
+ for (x = sc->args; x != sc->NIL; x = cdr(x)) {
+ v=num_mul(v,nvalue(car(x)));
+ }
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_number(sc, v));
+
+ CASE(OP_SUB): /* - */
+ if(cdr(sc->args)==sc->NIL) {
+ x=sc->args;
+ v=num_zero;
+ } else {
+ x = cdr(sc->args);
+ v = nvalue(car(sc->args));
+ }
+ for (; x != sc->NIL; x = cdr(x)) {
+ v=num_sub(v,nvalue(car(x)));
+ }
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_number(sc, v));
+
+ CASE(OP_DIV): /* / */
+ if(cdr(sc->args)==sc->NIL) {
+ x=sc->args;
+ v=num_one;
+ } else {
+ x = cdr(sc->args);
+ v = nvalue(car(sc->args));
+ }
+ for (; x != sc->NIL; x = cdr(x)) {
+ if (!is_zero_double(rvalue(car(x))))
+ v=num_div(v,nvalue(car(x)));
+ else {
+ Error_0(sc,"/: division by zero");
+ }
+ }
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_number(sc, v));
+
+ CASE(OP_INTDIV): /* quotient */
+ if(cdr(sc->args)==sc->NIL) {
+ x=sc->args;
+ v=num_one;
+ } else {
+ x = cdr(sc->args);
+ v = nvalue(car(sc->args));
+ }
+ for (; x != sc->NIL; x = cdr(x)) {
+ if (ivalue(car(x)) != 0)
+ v=num_intdiv(v,nvalue(car(x)));
+ else {
+ Error_0(sc,"quotient: division by zero");
+ }
+ }
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_number(sc, v));
+
+ CASE(OP_REM): /* remainder */
+ v = nvalue(car(sc->args));
+ if (ivalue(cadr(sc->args)) != 0)
+ v=num_rem(v,nvalue(cadr(sc->args)));
+ else {
+ Error_0(sc,"remainder: division by zero");
+ }
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_number(sc, v));
+
+ CASE(OP_MOD): /* modulo */
+ v = nvalue(car(sc->args));
+ if (ivalue(cadr(sc->args)) != 0)
+ v=num_mod(v,nvalue(cadr(sc->args)));
+ else {
+ Error_0(sc,"modulo: division by zero");
+ }
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_number(sc, v));
+
+ CASE(OP_CAR): /* car */
+ s_return(sc,caar(sc->args));
+
+ CASE(OP_CDR): /* cdr */
+ s_return(sc,cdar(sc->args));
+
+ CASE(OP_CONS): /* cons */
+ cdr(sc->args) = cadr(sc->args);
+ s_return(sc,sc->args);
+
+ CASE(OP_SETCAR): /* set-car! */
+ if(!is_immutable(car(sc->args))) {
+ caar(sc->args) = cadr(sc->args);
+ s_return(sc,car(sc->args));
+ } else {
+ Error_0(sc,"set-car!: unable to alter immutable pair");
+ }
+
+ CASE(OP_SETCDR): /* set-cdr! */
+ if(!is_immutable(car(sc->args))) {
+ cdar(sc->args) = cadr(sc->args);
+ s_return(sc,car(sc->args));
+ } else {
+ Error_0(sc,"set-cdr!: unable to alter immutable pair");
+ }
+
+ CASE(OP_CHAR2INT): { /* char->integer */
+ char c;
+ c=(char)ivalue(car(sc->args));
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_integer(sc, (unsigned char) c));
+ }
+
+ CASE(OP_INT2CHAR): { /* integer->char */
+ unsigned char c;
+ c=(unsigned char)ivalue(car(sc->args));
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_character(sc, (char) c));
+ }
+
+ CASE(OP_CHARUPCASE): {
+ unsigned char c;
+ c=(unsigned char)ivalue(car(sc->args));
+ c=toupper(c);
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_character(sc, (char) c));
+ }
+
+ CASE(OP_CHARDNCASE): {
+ unsigned char c;
+ c=(unsigned char)ivalue(car(sc->args));
+ c=tolower(c);
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_character(sc, (char) c));
+ }
+
+ CASE(OP_STR2SYM): /* string->symbol */
+ gc_disable(sc, gc_reservations (mk_symbol));
+ s_return_enable_gc(sc, mk_symbol(sc, strvalue(car(sc->args))));
+
+ CASE(OP_STR2ATOM): /* string->atom */ {
+ char *s=strvalue(car(sc->args));
+ long pf = 0;
+ if(cdr(sc->args)!=sc->NIL) {
+ /* we know cadr(sc->args) is a natural number */
+ /* see if it is 2, 8, 10, or 16, or error */
+ pf = ivalue_unchecked(cadr(sc->args));
+ if(pf == 16 || pf == 10 || pf == 8 || pf == 2) {
+ /* base is OK */
+ }
+ else {
+ pf = -1;
+ }
+ }
+ if (pf < 0) {
+ Error_1(sc, "string->atom: bad base", cadr(sc->args));
+ } else if(*s=='#') /* no use of base! */ {
+ s_return(sc, mk_sharp_const(sc, s+1));
+ } else {
+ if (pf == 0 || pf == 10) {
+ s_return(sc, mk_atom(sc, s));
+ }
+ else {
+ char *ep;
+ long iv = strtol(s,&ep,(int )pf);
+ if (*ep == 0) {
+ s_return(sc, mk_integer(sc, iv));
+ }
+ else {
+ s_return(sc, sc->F);
+ }
+ }
+ }
+ }
+
+ CASE(OP_SYM2STR): /* symbol->string */
+ gc_disable(sc, 1);
+ x=mk_string(sc,symname(car(sc->args)));
+ setimmutable(x);
+ s_return_enable_gc(sc, x);
+
+ CASE(OP_ATOM2STR): /* atom->string */ {
+ long pf = 0;
+ x=car(sc->args);
+ if(cdr(sc->args)!=sc->NIL) {
+ /* we know cadr(sc->args) is a natural number */
+ /* see if it is 2, 8, 10, or 16, or error */
+ pf = ivalue_unchecked(cadr(sc->args));
+ if(is_number(x) && (pf == 16 || pf == 10 || pf == 8 || pf == 2)) {
+ /* base is OK */
+ }
+ else {
+ pf = -1;
+ }
+ }
+ if (pf < 0) {
+ Error_1(sc, "atom->string: bad base", cadr(sc->args));
+ } else if(is_number(x) || is_character(x) || is_string(x) || is_symbol(x)) {
+ char *p;
+ int len;
+ atom2str(sc,x,(int )pf,&p,&len);
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_counted_string(sc, p, len));
+ } else {
+ Error_1(sc, "atom->string: not an atom", x);
+ }
+ }
+
+ CASE(OP_MKSTRING): { /* make-string */
+ int fill=' ';
+ int len;
+
+ len=ivalue(car(sc->args));
+
+ if(cdr(sc->args)!=sc->NIL) {
+ fill=charvalue(cadr(sc->args));
+ }
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_empty_string(sc, len, (char) fill));
+ }
+
+ CASE(OP_STRLEN): /* string-length */
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_integer(sc, strlength(car(sc->args))));
+
+ CASE(OP_STRREF): { /* string-ref */
+ char *str;
+ int index;
+
+ str=strvalue(car(sc->args));
+
+ index=ivalue(cadr(sc->args));
+
+ if(index>=strlength(car(sc->args))) {
+ Error_1(sc, "string-ref: out of bounds", cadr(sc->args));
+ }
+
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc,
+ mk_character(sc, ((unsigned char*) str)[index]));
+ }
+
+ CASE(OP_STRSET): { /* string-set! */
+ char *str;
+ int index;
+ int c;
+
+ if(is_immutable(car(sc->args))) {
+ Error_1(sc, "string-set!: unable to alter immutable string",
+ car(sc->args));
+ }
+ str=strvalue(car(sc->args));
+
+ index=ivalue(cadr(sc->args));
+ if(index>=strlength(car(sc->args))) {
+ Error_1(sc, "string-set!: out of bounds", cadr(sc->args));
+ }
+
+ c=charvalue(caddr(sc->args));
+
+ str[index]=(char)c;
+ s_return(sc,car(sc->args));
+ }
+
+ CASE(OP_STRAPPEND): { /* string-append */
+ /* in 1.29 string-append was in Scheme in init.scm but was too slow */
+ int len = 0;
+ pointer newstr;
+ char *pos;
+
+ /* compute needed length for new string */
+ for (x = sc->args; x != sc->NIL; x = cdr(x)) {
+ len += strlength(car(x));
+ }
+ gc_disable(sc, 1);
+ newstr = mk_empty_string(sc, len, ' ');
+ /* store the contents of the argument strings into the new string */
+ for (pos = strvalue(newstr), x = sc->args; x != sc->NIL;
+ pos += strlength(car(x)), x = cdr(x)) {
+ memcpy(pos, strvalue(car(x)), strlength(car(x)));
+ }
+ s_return_enable_gc(sc, newstr);
+ }
+
+ CASE(OP_SUBSTR): { /* substring */
+ char *str;
+ int index0;
+ int index1;
+
+ str=strvalue(car(sc->args));
+
+ index0=ivalue(cadr(sc->args));
+
+ if(index0>strlength(car(sc->args))) {
+ Error_1(sc, "substring: start out of bounds", cadr(sc->args));
+ }
+
+ if(cddr(sc->args)!=sc->NIL) {
+ index1=ivalue(caddr(sc->args));
+ if(index1>strlength(car(sc->args)) || index1<index0) {
+ Error_1(sc, "substring: end out of bounds", caddr(sc->args));
+ }
+ } else {
+ index1=strlength(car(sc->args));
+ }
+
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_counted_string(sc, str + index0, index1 - index0));
+ }
+
+ CASE(OP_VECTOR): { /* vector */
+ int i;
+ pointer vec;
+ int len=list_length(sc,sc->args);
+ if(len<0) {
+ Error_1(sc, "vector: not a proper list", sc->args);
+ }
+ vec=mk_vector(sc,len);
+ if(sc->no_memory) { s_return(sc, sc->sink); }
+ for (x = sc->args, i = 0; is_pair(x); x = cdr(x), i++) {
+ set_vector_elem(vec,i,car(x));
+ }
+ s_return(sc,vec);
+ }
+
+ CASE(OP_MKVECTOR): { /* make-vector */
+ pointer fill=sc->NIL;
+ int len;
+ pointer vec;
+
+ len=ivalue(car(sc->args));
+
+ if(cdr(sc->args)!=sc->NIL) {
+ fill=cadr(sc->args);
+ }
+ vec=mk_vector(sc,len);
+ if(sc->no_memory) { s_return(sc, sc->sink); }
+ if(fill!=sc->NIL) {
+ fill_vector(vec,fill);
+ }
+ s_return(sc,vec);
+ }
+
+ CASE(OP_VECLEN): /* vector-length */
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_integer(sc, vector_length(car(sc->args))));
+
+ CASE(OP_VECREF): { /* vector-ref */
+ int index;
+
+ index=ivalue(cadr(sc->args));
+
+ if(index >= vector_length(car(sc->args))) {
+ Error_1(sc, "vector-ref: out of bounds", cadr(sc->args));
+ }
+
+ s_return(sc,vector_elem(car(sc->args),index));
+ }
+
+ CASE(OP_VECSET): { /* vector-set! */
+ int index;
+
+ if(is_immutable(car(sc->args))) {
+ Error_1(sc, "vector-set!: unable to alter immutable vector",
+ car(sc->args));
+ }
+
+ index=ivalue(cadr(sc->args));
+ if(index >= vector_length(car(sc->args))) {
+ Error_1(sc, "vector-set!: out of bounds", cadr(sc->args));
+ }
+
+ set_vector_elem(car(sc->args),index,caddr(sc->args));
+ s_return(sc,car(sc->args));
+ }
+
+ CASE(OP_NOT): /* not */
+ s_retbool(is_false(car(sc->args)));
+ CASE(OP_BOOLP): /* boolean? */
+ s_retbool(car(sc->args) == sc->F || car(sc->args) == sc->T);
+ CASE(OP_EOFOBJP): /* boolean? */
+ s_retbool(car(sc->args) == sc->EOF_OBJ);
+ CASE(OP_NULLP): /* null? */
+ s_retbool(car(sc->args) == sc->NIL);
+ CASE(OP_NUMEQ): /* = */
+ /* Fallthrough. */
+ CASE(OP_LESS): /* < */
+ /* Fallthrough. */
+ CASE(OP_GRE): /* > */
+ /* Fallthrough. */
+ CASE(OP_LEQ): /* <= */
+ /* Fallthrough. */
+ CASE(OP_GEQ): /* >= */
+ switch(op) {
+ case OP_NUMEQ: comp_func=num_eq; break;
+ case OP_LESS: comp_func=num_lt; break;
+ case OP_GRE: comp_func=num_gt; break;
+ case OP_LEQ: comp_func=num_le; break;
+ case OP_GEQ: comp_func=num_ge; break;
+ default: assert (! "reached");
+ }
+ x=sc->args;
+ v=nvalue(car(x));
+ x=cdr(x);
+
+ for (; x != sc->NIL; x = cdr(x)) {
+ if(!comp_func(v,nvalue(car(x)))) {
+ s_retbool(0);
+ }
+ v=nvalue(car(x));
+ }
+ s_retbool(1);
+ CASE(OP_SYMBOLP): /* symbol? */
+ s_retbool(is_symbol(car(sc->args)));
+ CASE(OP_NUMBERP): /* number? */
+ s_retbool(is_number(car(sc->args)));
+ CASE(OP_STRINGP): /* string? */
+ s_retbool(is_string(car(sc->args)));
+ CASE(OP_INTEGERP): /* integer? */
+ s_retbool(is_integer(car(sc->args)));
+ CASE(OP_REALP): /* real? */
+ s_retbool(is_number(car(sc->args))); /* All numbers are real */
+ CASE(OP_CHARP): /* char? */
+ s_retbool(is_character(car(sc->args)));
+#if USE_CHAR_CLASSIFIERS
+ CASE(OP_CHARAP): /* char-alphabetic? */
+ s_retbool(Cisalpha(ivalue(car(sc->args))));
+ CASE(OP_CHARNP): /* char-numeric? */
+ s_retbool(Cisdigit(ivalue(car(sc->args))));
+ CASE(OP_CHARWP): /* char-whitespace? */
+ s_retbool(Cisspace(ivalue(car(sc->args))));
+ CASE(OP_CHARUP): /* char-upper-case? */
+ s_retbool(Cisupper(ivalue(car(sc->args))));
+ CASE(OP_CHARLP): /* char-lower-case? */
+ s_retbool(Cislower(ivalue(car(sc->args))));
+#endif
+ CASE(OP_PORTP): /* port? */
+ s_retbool(is_port(car(sc->args)));
+ CASE(OP_INPORTP): /* input-port? */
+ s_retbool(is_inport(car(sc->args)));
+ CASE(OP_OUTPORTP): /* output-port? */
+ s_retbool(is_outport(car(sc->args)));
+ CASE(OP_PROCP): /* procedure? */
+ /*--
+ * continuation should be procedure by the example
+ * (call-with-current-continuation procedure?) ==> #t
+ * in R^3 report sec. 6.9
+ */
+ s_retbool(is_proc(car(sc->args)) || is_closure(car(sc->args))
+ || is_continuation(car(sc->args)) || is_foreign(car(sc->args)));
+ CASE(OP_PAIRP): /* pair? */
+ s_retbool(is_pair(car(sc->args)));
+ CASE(OP_LISTP): /* list? */
+ s_retbool(list_length(sc,car(sc->args)) >= 0);
+
+ CASE(OP_ENVP): /* environment? */
+ s_retbool(is_environment(car(sc->args)));
+ CASE(OP_VECTORP): /* vector? */
+ s_retbool(is_vector(car(sc->args)));
+ CASE(OP_EQ): /* eq? */
+ s_retbool(car(sc->args) == cadr(sc->args));
+ CASE(OP_EQV): /* eqv? */
+ s_retbool(eqv(car(sc->args), cadr(sc->args)));
+
+ CASE(OP_FORCE): /* force */
+ sc->code = car(sc->args);
+ if (is_promise(sc->code)) {
+ /* Should change type to closure here */
+ s_save(sc, OP_SAVE_FORCED, sc->NIL, sc->code);
+ sc->args = sc->NIL;
+ s_thread_to(sc,OP_APPLY);
+ } else {
+ s_return(sc,sc->code);
+ }
+
+ CASE(OP_SAVE_FORCED): /* Save forced value replacing promise */
+ copy_value(sc, sc->code, sc->value);
+ s_return(sc,sc->value);
+
+ CASE(OP_WRITE): /* write */
+ /* Fallthrough. */
+ CASE(OP_DISPLAY): /* display */
+ /* Fallthrough. */
+ CASE(OP_WRITE_CHAR): /* write-char */
+ if(is_pair(cdr(sc->args))) {
+ if(cadr(sc->args)!=sc->outport) {
+ x=cons(sc,sc->outport,sc->NIL);
+ s_save(sc,OP_SET_OUTPORT, x, sc->NIL);
+ sc->outport=cadr(sc->args);
+ }
+ }
+ sc->args = car(sc->args);
+ if(op==OP_WRITE) {
+ sc->print_flag = 1;
+ } else {
+ sc->print_flag = 0;
+ }
+ s_thread_to(sc,OP_P0LIST);
+
+ CASE(OP_NEWLINE): /* newline */
+ if(is_pair(sc->args)) {
+ if(car(sc->args)!=sc->outport) {
+ x=cons(sc,sc->outport,sc->NIL);
+ s_save(sc,OP_SET_OUTPORT, x, sc->NIL);
+ sc->outport=car(sc->args);
+ }
+ }
+ putstr(sc, "\n");
+ s_return(sc,sc->T);
+
+ CASE(OP_ERR0): /* error */
+ sc->retcode=-1;
+ if (!is_string(car(sc->args))) {
+ sc->args=cons(sc,mk_string(sc," -- "),sc->args);
+ setimmutable(car(sc->args));
+ }
+ putstr(sc, "Error: ");
+ putstr(sc, strvalue(car(sc->args)));
+ sc->args = cdr(sc->args);
+ s_thread_to(sc,OP_ERR1);
+
+ CASE(OP_ERR1): /* error */
+ putstr(sc, " ");
+ if (sc->args != sc->NIL) {
+ s_save(sc,OP_ERR1, cdr(sc->args), sc->NIL);
+ sc->args = car(sc->args);
+ sc->print_flag = 1;
+ s_thread_to(sc,OP_P0LIST);
+ } else {
+ putstr(sc, "\n");
+ if(sc->interactive_repl) {
+ s_thread_to(sc,OP_T0LVL);
+ } else {
+ return;
+ }
+ }
+
+ CASE(OP_REVERSE): /* reverse */
+ s_return(sc,reverse(sc, sc->NIL, car(sc->args)));
+
+ CASE(OP_REVERSE_IN_PLACE): /* reverse! */
+ s_return(sc, reverse_in_place(sc, sc->NIL, car(sc->args)));
+
+ CASE(OP_LIST_STAR): /* list* */
+ s_return(sc,list_star(sc,sc->args));
+
+ CASE(OP_APPEND): /* append */
+ x = sc->NIL;
+ y = sc->args;
+ if (y == x) {
+ s_return(sc, x);
+ }
+
+ /* cdr() in the while condition is not a typo. If car() */
+ /* is used (append '() 'a) will return the wrong result.*/
+ while (cdr(y) != sc->NIL) {
+ x = revappend(sc, x, car(y));
+ y = cdr(y);
+ if (x == sc->F) {
+ Error_0(sc, "non-list argument to append");
+ }
+ }
+
+ s_return(sc, reverse_in_place(sc, car(y), x));
+
+#if USE_PLIST
+ CASE(OP_SET_SYMBOL_PROPERTY): /* set-symbol-property! */
+ gc_disable(sc, gc_reservations(set_property));
+ s_return_enable_gc(sc,
+ set_property(sc, car(sc->args),
+ cadr(sc->args), caddr(sc->args)));
+
+ CASE(OP_SYMBOL_PROPERTY): /* symbol-property */
+ s_return(sc, get_property(sc, car(sc->args), cadr(sc->args)));
+#endif /* USE_PLIST */
+
+ CASE(OP_TAG_VALUE): { /* not exposed */
+ /* This tags sc->value with car(sc->args). Useful to tag
+ * results of opcode evaluations. */
+ pointer a, b, c;
+ free_cons(sc, sc->args, &a, &b);
+ free_cons(sc, b, &b, &c);
+ assert(c == sc->NIL);
+ s_return(sc, mk_tagged_value(sc, sc->value, a, b));
+ }
+
+ CASE(OP_MK_TAGGED): /* make-tagged-value */
+ if (is_vector(car(sc->args)))
+ Error_0(sc, "cannot tag vector");
+ s_return(sc, mk_tagged_value(sc, car(sc->args),
+ car(cadr(sc->args)),
+ cdr(cadr(sc->args))));
+
+ CASE(OP_GET_TAG): /* get-tag */
+ s_return(sc, get_tag(sc, car(sc->args)));
+
+ CASE(OP_QUIT): /* quit */
+ if(is_pair(sc->args)) {
+ sc->retcode=ivalue(car(sc->args));
+ }
+ return;
+
+ CASE(OP_GC): /* gc */
+ gc(sc, sc->NIL, sc->NIL);
+ s_return(sc,sc->T);
+
+ CASE(OP_GCVERB): /* gc-verbose */
+ { int was = sc->gc_verbose;
+
+ sc->gc_verbose = (car(sc->args) != sc->F);
+ s_retbool(was);
+ }
+
+ CASE(OP_NEWSEGMENT): /* new-segment */
+ if (!is_pair(sc->args) || !is_number(car(sc->args))) {
+ Error_0(sc,"new-segment: argument must be a number");
+ }
+ alloc_cellseg(sc, (int) ivalue(car(sc->args)));
+ s_return(sc,sc->T);
+
+ CASE(OP_OBLIST): /* oblist */
+ s_return(sc, oblist_all_symbols(sc));
+
+ CASE(OP_CURR_INPORT): /* current-input-port */
+ s_return(sc,sc->inport);
+
+ CASE(OP_CURR_OUTPORT): /* current-output-port */
+ s_return(sc,sc->outport);
+
+ CASE(OP_OPEN_INFILE): /* open-input-file */
+ /* Fallthrough. */
+ CASE(OP_OPEN_OUTFILE): /* open-output-file */
+ /* Fallthrough. */
+ CASE(OP_OPEN_INOUTFILE): /* open-input-output-file */ {
+ int prop=0;
+ pointer p;
+ switch(op) {
+ case OP_OPEN_INFILE: prop=port_input; break;
+ case OP_OPEN_OUTFILE: prop=port_output; break;
+ case OP_OPEN_INOUTFILE: prop=port_input|port_output; break;
+ default: assert (! "reached");
+ }
+ p=port_from_filename(sc,strvalue(car(sc->args)),prop);
+ if(p==sc->NIL) {
+ s_return(sc,sc->F);
+ }
+ s_return(sc,p);
+ break;
+ }
+
+#if USE_STRING_PORTS
+ CASE(OP_OPEN_INSTRING): /* open-input-string */
+ /* Fallthrough. */
+ CASE(OP_OPEN_INOUTSTRING): /* open-input-output-string */ {
+ int prop=0;
+ pointer p;
+ switch(op) {
+ case OP_OPEN_INSTRING: prop=port_input; break;
+ case OP_OPEN_INOUTSTRING: prop=port_input|port_output; break;
+ default: assert (! "reached");
+ }
+ p=port_from_string(sc, strvalue(car(sc->args)),
+ strvalue(car(sc->args))+strlength(car(sc->args)), prop);
+ if(p==sc->NIL) {
+ s_return(sc,sc->F);
+ }
+ s_return(sc,p);
+ }
+ CASE(OP_OPEN_OUTSTRING): /* open-output-string */ {
+ pointer p;
+ if(car(sc->args)==sc->NIL) {
+ p=port_from_scratch(sc);
+ if(p==sc->NIL) {
+ s_return(sc,sc->F);
+ }
+ } else {
+ p=port_from_string(sc, strvalue(car(sc->args)),
+ strvalue(car(sc->args))+strlength(car(sc->args)),
+ port_output);
+ if(p==sc->NIL) {
+ s_return(sc,sc->F);
+ }
+ }
+ s_return(sc,p);
+ }
+ CASE(OP_GET_OUTSTRING): /* get-output-string */ {
+ port *p;
+
+ if ((p=car(sc->args)->_object._port)->kind&port_string) {
+ gc_disable(sc, 1);
+ s_return_enable_gc(
+ sc,
+ mk_counted_string(sc,
+ p->rep.string.start,
+ p->rep.string.curr - p->rep.string.start));
+ }
+ s_return(sc,sc->F);
+ }
+#endif
+
+ CASE(OP_CLOSE_INPORT): /* close-input-port */
+ port_close(sc,car(sc->args),port_input);
+ s_return(sc,sc->T);
+
+ CASE(OP_CLOSE_OUTPORT): /* close-output-port */
+ port_close(sc,car(sc->args),port_output);
+ s_return(sc,sc->T);
+
+ CASE(OP_INT_ENV): /* interaction-environment */
+ s_return(sc,sc->global_env);
+
+ CASE(OP_CURR_ENV): /* current-environment */
+ s_return(sc,sc->envir);
+
+
+ /* ========== reading part ========== */
+ CASE(OP_READ):
+ if(!is_pair(sc->args)) {
+ s_thread_to(sc,OP_READ_INTERNAL);
+ }
+ if(!is_inport(car(sc->args))) {
+ Error_1(sc, "read: not an input port", car(sc->args));
+ }
+ if(car(sc->args)==sc->inport) {
+ s_thread_to(sc,OP_READ_INTERNAL);
+ }
+ x=sc->inport;
+ sc->inport=car(sc->args);
+ x=cons(sc,x,sc->NIL);
+ s_save(sc,OP_SET_INPORT, x, sc->NIL);
+ s_thread_to(sc,OP_READ_INTERNAL);
+
+ CASE(OP_READ_CHAR): /* read-char */
+ /* Fallthrough. */
+ CASE(OP_PEEK_CHAR): /* peek-char */ {
+ int c;
+ if(is_pair(sc->args)) {
+ if(car(sc->args)!=sc->inport) {
+ x=sc->inport;
+ x=cons(sc,x,sc->NIL);
+ s_save(sc,OP_SET_INPORT, x, sc->NIL);
+ sc->inport=car(sc->args);
+ }
+ }
+ c=inchar(sc);
+ if(c==EOF) {
+ s_return(sc,sc->EOF_OBJ);
+ }
+ if(op==OP_PEEK_CHAR) {
+ backchar(sc,c);
+ }
+ s_return(sc,mk_character(sc,c));
+ }
+
+ CASE(OP_CHAR_READY): /* char-ready? */ {
+ pointer p=sc->inport;
+ int res;
+ if(is_pair(sc->args)) {
+ p=car(sc->args);
+ }
+ res=p->_object._port->kind&port_string;
+ s_retbool(res);
+ }
+
+ CASE(OP_SET_INPORT): /* set-input-port */
+ sc->inport=car(sc->args);
+ s_return(sc,sc->value);
+
+ CASE(OP_SET_OUTPORT): /* set-output-port */
+ sc->outport=car(sc->args);
+ s_return(sc,sc->value);
+
+ CASE(OP_RDSEXPR):
+ switch (sc->tok) {
+ case TOK_EOF:
+ s_return(sc,sc->EOF_OBJ);
+ /* NOTREACHED */
+ case TOK_VEC:
+ s_save(sc,OP_RDVEC,sc->NIL,sc->NIL);
+ /* fall through */
+ case TOK_LPAREN:
+ sc->tok = token(sc);
+ if (sc->tok == TOK_RPAREN) {
+ s_return(sc,sc->NIL);
+ } else if (sc->tok == TOK_DOT) {
+ Error_0(sc,"syntax error: illegal dot expression");
+ } else {
+#if SHOW_ERROR_LINE
+ pointer filename;
+ pointer lineno;
+#endif
+ sc->nesting_stack[sc->file_i]++;
+#if SHOW_ERROR_LINE
+ filename = sc->load_stack[sc->file_i].filename;
+ lineno = sc->load_stack[sc->file_i].curr_line;
+
+ s_save(sc, OP_TAG_VALUE,
+ cons(sc, filename, cons(sc, lineno, sc->NIL)),
+ sc->NIL);
+#endif
+ s_save(sc,OP_RDLIST, sc->NIL, sc->NIL);
+ s_thread_to(sc,OP_RDSEXPR);
+ }
+ case TOK_QUOTE:
+ s_save(sc,OP_RDQUOTE, sc->NIL, sc->NIL);
+ sc->tok = token(sc);
+ s_thread_to(sc,OP_RDSEXPR);
+ case TOK_BQUOTE:
+ sc->tok = token(sc);
+ if(sc->tok==TOK_VEC) {
+ s_save(sc,OP_RDQQUOTEVEC, sc->NIL, sc->NIL);
+ sc->tok=TOK_LPAREN;
+ s_thread_to(sc,OP_RDSEXPR);
+ } else {
+ s_save(sc,OP_RDQQUOTE, sc->NIL, sc->NIL);
+ }
+ s_thread_to(sc,OP_RDSEXPR);
+ case TOK_COMMA:
+ s_save(sc,OP_RDUNQUOTE, sc->NIL, sc->NIL);
+ sc->tok = token(sc);
+ s_thread_to(sc,OP_RDSEXPR);
+ case TOK_ATMARK:
+ s_save(sc,OP_RDUQTSP, sc->NIL, sc->NIL);
+ sc->tok = token(sc);
+ s_thread_to(sc,OP_RDSEXPR);
+ case TOK_ATOM:
+ s_return(sc,mk_atom(sc, readstr_upto(sc, DELIMITERS)));
+ case TOK_DQUOTE:
+ x=readstrexp(sc);
+ if(x==sc->F) {
+ Error_0(sc,"Error reading string");
+ }
+ setimmutable(x);
+ s_return(sc,x);
+ case TOK_SHARP: {
+ pointer f=find_slot_in_env(sc,sc->envir,sc->SHARP_HOOK,1);
+ if(f==sc->NIL) {
+ Error_0(sc,"undefined sharp expression");
+ } else {
+ sc->code=cons(sc,slot_value_in_env(f),sc->NIL);
+ s_thread_to(sc,OP_EVAL);
+ }
+ }
+ case TOK_SHARP_CONST:
+ if ((x = mk_sharp_const(sc, readstr_upto(sc, DELIMITERS))) == sc->NIL) {
+ Error_0(sc,"undefined sharp expression");
+ } else {
+ s_return(sc,x);
+ }
+ default:
+ Error_0(sc,"syntax error: illegal token");
+ }
+ break;
+
+ CASE(OP_RDLIST): {
+ gc_disable(sc, 1);
+ sc->args = cons(sc, sc->value, sc->args);
+ gc_enable(sc);
+ sc->tok = token(sc);
+ if (sc->tok == TOK_EOF)
+ { s_return(sc,sc->EOF_OBJ); }
+ else if (sc->tok == TOK_RPAREN) {
+ int c = inchar(sc);
+ if (c != '\n')
+ backchar(sc,c);
+ else
+ port_increment_current_line(sc, &sc->load_stack[sc->file_i], 1);
+ sc->nesting_stack[sc->file_i]--;
+ s_return(sc,reverse_in_place(sc, sc->NIL, sc->args));
+ } else if (sc->tok == TOK_DOT) {
+ s_save(sc,OP_RDDOT, sc->args, sc->NIL);
+ sc->tok = token(sc);
+ s_thread_to(sc,OP_RDSEXPR);
+ } else {
+ s_save(sc,OP_RDLIST, sc->args, sc->NIL);;
+ s_thread_to(sc,OP_RDSEXPR);
+ }
+ }
+
+ CASE(OP_RDDOT):
+ if (token(sc) != TOK_RPAREN) {
+ Error_0(sc,"syntax error: illegal dot expression");
+ } else {
+ sc->nesting_stack[sc->file_i]--;
+ s_return(sc,reverse_in_place(sc, sc->value, sc->args));
+ }
+
+ CASE(OP_RDQUOTE):
+ gc_disable(sc, 2);
+ s_return_enable_gc(sc, cons(sc, sc->QUOTE,
+ cons(sc, sc->value, sc->NIL)));
+
+ CASE(OP_RDQQUOTE):
+ gc_disable(sc, 2);
+ s_return_enable_gc(sc, cons(sc, sc->QQUOTE,
+ cons(sc, sc->value, sc->NIL)));
+
+ CASE(OP_RDQQUOTEVEC):
+ gc_disable(sc, 5 + 2 * gc_reservations (mk_symbol));
+ s_return_enable_gc(sc,cons(sc, mk_symbol(sc,"apply"),
+ cons(sc, mk_symbol(sc,"vector"),
+ cons(sc,cons(sc, sc->QQUOTE,
+ cons(sc,sc->value,sc->NIL)),
+ sc->NIL))));
+
+ CASE(OP_RDUNQUOTE):
+ gc_disable(sc, 2);
+ s_return_enable_gc(sc, cons(sc, sc->UNQUOTE,
+ cons(sc, sc->value, sc->NIL)));
+
+ CASE(OP_RDUQTSP):
+ gc_disable(sc, 2);
+ s_return_enable_gc(sc, cons(sc, sc->UNQUOTESP,
+ cons(sc, sc->value, sc->NIL)));
+
+ CASE(OP_RDVEC):
+ /*sc->code=cons(sc,mk_proc(sc,OP_VECTOR),sc->value);
+ s_thread_to(sc,OP_EVAL); Cannot be quoted*/
+ /*x=cons(sc,mk_proc(sc,OP_VECTOR),sc->value);
+ s_return(sc,x); Cannot be part of pairs*/
+ /*sc->code=mk_proc(sc,OP_VECTOR);
+ sc->args=sc->value;
+ s_thread_to(sc,OP_APPLY);*/
+ sc->args=sc->value;
+ s_thread_to(sc,OP_VECTOR);
+
+ /* ========== printing part ========== */
+ CASE(OP_P0LIST):
+ if(is_vector(sc->args)) {
+ putstr(sc,"#(");
+ sc->args=cons(sc,sc->args,mk_integer(sc,0));
+ s_thread_to(sc,OP_PVECFROM);
+ } else if(is_environment(sc->args)) {
+ putstr(sc,"#<ENVIRONMENT>");
+ s_return(sc,sc->T);
+ } else if (!is_pair(sc->args)) {
+ printatom(sc, sc->args, sc->print_flag);
+ s_return(sc,sc->T);
+ } else if (car(sc->args) == sc->QUOTE && ok_abbrev(cdr(sc->args))) {
+ putstr(sc, "'");
+ sc->args = cadr(sc->args);
+ s_thread_to(sc,OP_P0LIST);
+ } else if (car(sc->args) == sc->QQUOTE && ok_abbrev(cdr(sc->args))) {
+ putstr(sc, "`");
+ sc->args = cadr(sc->args);
+ s_thread_to(sc,OP_P0LIST);
+ } else if (car(sc->args) == sc->UNQUOTE && ok_abbrev(cdr(sc->args))) {
+ putstr(sc, ",");
+ sc->args = cadr(sc->args);
+ s_thread_to(sc,OP_P0LIST);
+ } else if (car(sc->args) == sc->UNQUOTESP && ok_abbrev(cdr(sc->args))) {
+ putstr(sc, ",@");
+ sc->args = cadr(sc->args);
+ s_thread_to(sc,OP_P0LIST);
+ } else {
+ putstr(sc, "(");
+ s_save(sc,OP_P1LIST, cdr(sc->args), sc->NIL);
+ sc->args = car(sc->args);
+ s_thread_to(sc,OP_P0LIST);
+ }
+
+ CASE(OP_P1LIST):
+ if (is_pair(sc->args)) {
+ s_save(sc,OP_P1LIST, cdr(sc->args), sc->NIL);
+ putstr(sc, " ");
+ sc->args = car(sc->args);
+ s_thread_to(sc,OP_P0LIST);
+ } else if(is_vector(sc->args)) {
+ s_save(sc,OP_P1LIST,sc->NIL,sc->NIL);
+ putstr(sc, " . ");
+ s_thread_to(sc,OP_P0LIST);
+ } else {
+ if (sc->args != sc->NIL) {
+ putstr(sc, " . ");
+ printatom(sc, sc->args, sc->print_flag);
+ }
+ putstr(sc, ")");
+ s_return(sc,sc->T);
+ }
+ CASE(OP_PVECFROM): {
+ int i=ivalue_unchecked(cdr(sc->args));
+ pointer vec=car(sc->args);
+ int len = vector_length(vec);
+ if(i==len) {
+ putstr(sc,")");
+ s_return(sc,sc->T);
+ } else {
+ pointer elem=vector_elem(vec,i);
+ cdr(sc->args) = mk_integer(sc, i + 1);
+ s_save(sc,OP_PVECFROM, sc->args, sc->NIL);
+ sc->args=elem;
+ if (i > 0)
+ putstr(sc," ");
+ s_thread_to(sc,OP_P0LIST);
+ }
+ }
+
+ CASE(OP_LIST_LENGTH): { /* length */ /* a.k */
+ long l = list_length(sc, car(sc->args));
+ if(l<0) {
+ Error_1(sc, "length: not a list", car(sc->args));
+ }
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, mk_integer(sc, l));
+ }
+ CASE(OP_ASSQ): /* assq */ /* a.k */
+ x = car(sc->args);
+ for (y = cadr(sc->args); is_pair(y); y = cdr(y)) {
+ if (!is_pair(car(y))) {
+ Error_0(sc,"unable to handle non pair element");
+ }
+ if (x == caar(y))
+ break;
+ }
+ if (is_pair(y)) {
+ s_return(sc,car(y));
+ } else {
+ s_return(sc,sc->F);
+ }
+
+
+ CASE(OP_GET_CLOSURE): /* get-closure-code */ /* a.k */
+ sc->args = car(sc->args);
+ if (sc->args == sc->NIL) {
+ s_return(sc,sc->F);
+ } else if (is_closure(sc->args)) {
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, cons(sc, sc->LAMBDA,
+ closure_code(sc->value)));
+ } else if (is_macro(sc->args)) {
+ gc_disable(sc, 1);
+ s_return_enable_gc(sc, cons(sc, sc->LAMBDA,
+ closure_code(sc->value)));
+ } else {
+ s_return(sc,sc->F);
+ }
+ CASE(OP_CLOSUREP): /* closure? */
+ /*
+ * Note, macro object is also a closure.
+ * Therefore, (closure? <#MACRO>) ==> #t
+ */
+ s_retbool(is_closure(car(sc->args)));
+ CASE(OP_MACROP): /* macro? */
+ s_retbool(is_macro(car(sc->args)));
+ CASE(OP_VM_HISTORY): /* *vm-history* */
+ s_return(sc, history_flatten(sc));
+ default:
+ snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", op);
+ Error_0(sc,sc->strbuff);
+ }
+ }
+}
+
+#if GPGRT_GCC_VERSION >= 80000
+# pragma GCC diagnostic pop
+#endif
+
+
+typedef int (*test_predicate)(pointer);
+
+static int is_any(pointer p) {
+ (void)p;
+ return 1;
+}
+
+static int is_nonneg(pointer p) {
+ return ivalue(p)>=0 && is_integer(p);
+}
+
+/* Correspond carefully with following defines! */
+static const struct {
+ test_predicate fct;
+ const char *kind;
+} tests[]={
+ {0,0}, /* unused */
+ {is_any, 0},
+ {is_string, "string"},
+ {is_symbol, "symbol"},
+ {is_port, "port"},
+ {is_inport,"input port"},
+ {is_outport,"output port"},
+ {is_environment, "environment"},
+ {is_pair, "pair"},
+ {0, "pair or '()"},
+ {is_character, "character"},
+ {is_vector, "vector"},
+ {is_number, "number"},
+ {is_integer, "integer"},
+ {is_nonneg, "non-negative integer"}
+};
+
+#define TST_NONE 0
+#define TST_ANY "\001"
+#define TST_STRING "\002"
+#define TST_SYMBOL "\003"
+#define TST_PORT "\004"
+#define TST_INPORT "\005"
+#define TST_OUTPORT "\006"
+#define TST_ENVIRONMENT "\007"
+#define TST_PAIR "\010"
+#define TST_LIST "\011"
+#define TST_CHAR "\012"
+#define TST_VECTOR "\013"
+#define TST_NUMBER "\014"
+#define TST_INTEGER "\015"
+#define TST_NATURAL "\016"
+
+#define INF_ARG 0xff
+
+static const struct op_code_info dispatch_table[]= {
+#define _OP_DEF(A,B,C,D,OP) {{A},B,C,{D}},
+#include "opdefines.h"
+#undef _OP_DEF
+ {{0},0,0,{0}},
+};
+
+static const char *procname(pointer x) {
+ int n=procnum(x);
+ const char *name=dispatch_table[n].name;
+ if (name[0] == 0) {
+ name="ILLEGAL!";
+ }
+ return name;
+}
+
+static int
+check_arguments (scheme *sc, const struct op_code_info *pcd, char *msg, size_t msg_size)
+{
+ int ok = 1;
+ int n = list_length(sc, sc->args);
+
+ /* Check number of arguments */
+ if (n < pcd->min_arity) {
+ ok = 0;
+ snprintf(msg, msg_size, "%s: needs%s %d argument(s)",
+ pcd->name,
+ pcd->min_arity == pcd->max_arity ? "" : " at least",
+ pcd->min_arity);
+ }
+ if (ok && n>pcd->max_arity) {
+ ok = 0;
+ snprintf(msg, msg_size, "%s: needs%s %d argument(s)",
+ pcd->name,
+ pcd->min_arity == pcd->max_arity ? "" : " at most",
+ pcd->max_arity);
+ }
+ if (ok) {
+ if (pcd->arg_tests_encoding[0] != 0) {
+ int i = 0;
+ int j;
+ const char *t = pcd->arg_tests_encoding;
+ pointer arglist = sc->args;
+
+ do {
+ pointer arg = car(arglist);
+ j = (int)t[0];
+ if (j == TST_LIST[0]) {
+ if (arg != sc->NIL && !is_pair(arg)) break;
+ } else {
+ if (!tests[j].fct(arg)) break;
+ }
+
+ if (t[1] != 0 && i < sizeof pcd->arg_tests_encoding) {
+ /* last test is replicated as necessary */
+ t++;
+ }
+ arglist = cdr(arglist);
+ i++;
+ } while (i < n);
+
+ if (i < n) {
+ ok = 0;
+ snprintf(msg, msg_size, "%s: argument %d must be: %s, got: %s",
+ pcd->name,
+ i + 1,
+ tests[j].kind,
+ type_to_string(type(car(arglist))));
+ }
+ }
+ }
+
+ return ok;
+}
+
+/* ========== Initialization of internal keywords ========== */
+
+/* Symbols representing syntax are tagged with (OP . '()). */
+static void assign_syntax(scheme *sc, enum scheme_opcodes op, char *name) {
+ pointer x, y;
+ pointer *slot;
+
+ x = oblist_find_by_name(sc, name, &slot);
+ assert (x == sc->NIL);
+
+ x = immutable_cons(sc, mk_string(sc, name), sc->NIL);
+ typeflag(x) = T_SYMBOL | T_SYNTAX;
+ setimmutable(car(x));
+ y = mk_tagged_value(sc, x, mk_integer(sc, op), sc->NIL);
+ free_cell(sc, x);
+ setimmutable(get_tag(sc, y));
+ *slot = immutable_cons(sc, y, *slot);
+}
+
+/* Returns the opcode for the syntax represented by P. */
+static int syntaxnum(scheme *sc, pointer p) {
+ int op = ivalue_unchecked(car(get_tag(sc, p)));
+ assert (op < OP_MAXDEFINED);
+ return op;
+}
+
+static void assign_proc(scheme *sc, enum scheme_opcodes op, const char *name) {
+ pointer x, y;
+
+ x = mk_symbol(sc, name);
+ y = mk_proc(sc,op);
+ new_slot_in_env(sc, x, y);
+}
+
+static pointer mk_proc(scheme *sc, enum scheme_opcodes op) {
+ pointer y;
+
+ y = get_cell(sc, sc->NIL, sc->NIL);
+ typeflag(y) = (T_PROC | T_ATOM);
+ ivalue_unchecked(y) = (long) op;
+ set_num_integer(y);
+ return y;
+}
+
+/* initialization of TinyScheme */
+#if USE_INTERFACE
+INTERFACE static pointer s_cons(scheme *sc, pointer a, pointer b) {
+ return cons(sc,a,b);
+}
+INTERFACE static pointer s_immutable_cons(scheme *sc, pointer a, pointer b) {
+ return immutable_cons(sc,a,b);
+}
+
+static const struct scheme_interface vtbl = {
+ scheme_define,
+ s_cons,
+ s_immutable_cons,
+ reserve_cells,
+ mk_integer,
+ mk_real,
+ mk_symbol,
+ gensym,
+ mk_string,
+ mk_counted_string,
+ mk_character,
+ mk_vector,
+ mk_foreign_func,
+ mk_foreign_object,
+ get_foreign_object_vtable,
+ get_foreign_object_data,
+ putstr,
+ putcharacter,
+
+ is_string,
+ string_value,
+ is_number,
+ nvalue,
+ ivalue,
+ rvalue,
+ is_integer,
+ is_real,
+ is_character,
+ charvalue,
+ is_list,
+ is_vector,
+ list_length,
+ ivalue,
+ fill_vector,
+ vector_elem,
+ set_vector_elem,
+ is_port,
+ is_pair,
+ pair_car,
+ pair_cdr,
+ set_car,
+ set_cdr,
+
+ is_symbol,
+ symname,
+
+ is_syntax,
+ is_proc,
+ is_foreign,
+ syntaxname,
+ is_closure,
+ is_macro,
+ closure_code,
+ closure_env,
+
+ is_continuation,
+ is_promise,
+ is_environment,
+ is_immutable,
+ setimmutable,
+
+ scheme_load_file,
+ scheme_load_string,
+ port_from_file
+};
+#endif
+
+scheme *scheme_init_new() {
+ scheme *sc=(scheme*)malloc(sizeof(scheme));
+ if(!scheme_init(sc)) {
+ free(sc);
+ return 0;
+ } else {
+ return sc;
+ }
+}
+
+scheme *scheme_init_new_custom_alloc(func_alloc malloc, func_dealloc free) {
+ scheme *sc=(scheme*)malloc(sizeof(scheme));
+ if(!scheme_init_custom_alloc(sc,malloc,free)) {
+ free(sc);
+ return 0;
+ } else {
+ return sc;
+ }
+}
+
+
+int scheme_init(scheme *sc) {
+ return scheme_init_custom_alloc(sc,malloc,free);
+}
+
+int scheme_init_custom_alloc(scheme *sc, func_alloc malloc, func_dealloc free) {
+ int i, n=sizeof(dispatch_table)/sizeof(dispatch_table[0]);
+ pointer x;
+
+#if USE_INTERFACE
+ sc->vptr=&vtbl;
+#endif
+ sc->gensym_cnt=0;
+ sc->malloc=malloc;
+ sc->free=free;
+ sc->sink = &sc->_sink;
+ sc->NIL = &sc->_NIL;
+ sc->T = &sc->_HASHT;
+ sc->F = &sc->_HASHF;
+ sc->EOF_OBJ=&sc->_EOF_OBJ;
+
+ sc->free_cell = &sc->_NIL;
+ sc->fcells = 0;
+ sc->inhibit_gc = GC_ENABLED;
+ sc->reserved_cells = 0;
+#ifndef NDEBUG
+ sc->reserved_lineno = 0;
+#endif
+ sc->no_memory=0;
+ sc->inport=sc->NIL;
+ sc->outport=sc->NIL;
+ sc->save_inport=sc->NIL;
+ sc->loadport=sc->NIL;
+ sc->nesting=0;
+ memset (sc->nesting_stack, 0, sizeof sc->nesting_stack);
+ sc->interactive_repl=0;
+ sc->strbuff = sc->malloc(STRBUFFSIZE);
+ if (sc->strbuff == 0) {
+ sc->no_memory=1;
+ return 0;
+ }
+ sc->strbuff_size = STRBUFFSIZE;
+
+ sc->cell_segments = NULL;
+ if (alloc_cellseg(sc,FIRST_CELLSEGS) != FIRST_CELLSEGS) {
+ sc->no_memory=1;
+ return 0;
+ }
+ sc->gc_verbose = 0;
+ dump_stack_initialize(sc);
+ sc->code = sc->NIL;
+ sc->tracing=0;
+ sc->flags = 0;
+
+ /* init sc->NIL */
+ typeflag(sc->NIL) = (T_NIL | T_ATOM | MARK);
+ car(sc->NIL) = cdr(sc->NIL) = sc->NIL;
+ /* init T */
+ typeflag(sc->T) = (T_BOOLEAN | T_ATOM | MARK);
+ car(sc->T) = cdr(sc->T) = sc->T;
+ /* init F */
+ typeflag(sc->F) = (T_BOOLEAN | T_ATOM | MARK);
+ car(sc->F) = cdr(sc->F) = sc->F;
+ /* init EOF_OBJ */
+ typeflag(sc->EOF_OBJ) = (T_EOF_OBJ | T_ATOM | MARK);
+ car(sc->EOF_OBJ) = cdr(sc->EOF_OBJ) = sc->EOF_OBJ;
+ /* init sink */
+ typeflag(sc->sink) = (T_SINK | T_PAIR | MARK);
+ car(sc->sink) = cdr(sc->sink) = sc->NIL;
+ /* init c_nest */
+ sc->c_nest = sc->NIL;
+
+ sc->oblist = oblist_initial_value(sc);
+ /* init global_env */
+ new_frame_in_env(sc, sc->NIL);
+ sc->global_env = sc->envir;
+ /* init else */
+ x = mk_symbol(sc,"else");
+ new_slot_in_env(sc, x, sc->T);
+
+ assign_syntax(sc, OP_LAMBDA, "lambda");
+ assign_syntax(sc, OP_QUOTE, "quote");
+ assign_syntax(sc, OP_DEF0, "define");
+ assign_syntax(sc, OP_IF0, "if");
+ assign_syntax(sc, OP_BEGIN, "begin");
+ assign_syntax(sc, OP_SET0, "set!");
+ assign_syntax(sc, OP_LET0, "let");
+ assign_syntax(sc, OP_LET0AST, "let*");
+ assign_syntax(sc, OP_LET0REC, "letrec");
+ assign_syntax(sc, OP_COND0, "cond");
+ assign_syntax(sc, OP_DELAY, "delay");
+ assign_syntax(sc, OP_AND0, "and");
+ assign_syntax(sc, OP_OR0, "or");
+ assign_syntax(sc, OP_C0STREAM, "cons-stream");
+ assign_syntax(sc, OP_MACRO0, "macro");
+ assign_syntax(sc, OP_CASE0, "case");
+
+ for(i=0; i<n; i++) {
+ if (dispatch_table[i].name[0] != 0) {
+ assign_proc(sc, (enum scheme_opcodes)i, dispatch_table[i].name);
+ }
+ }
+
+ history_init(sc, 8, 8);
+
+ /* initialization of global pointers to special symbols */
+ sc->LAMBDA = mk_symbol(sc, "lambda");
+ sc->QUOTE = mk_symbol(sc, "quote");
+ sc->QQUOTE = mk_symbol(sc, "quasiquote");
+ sc->UNQUOTE = mk_symbol(sc, "unquote");
+ sc->UNQUOTESP = mk_symbol(sc, "unquote-splicing");
+ sc->FEED_TO = mk_symbol(sc, "=>");
+ sc->COLON_HOOK = mk_symbol(sc,"*colon-hook*");
+ sc->ERROR_HOOK = mk_symbol(sc, "*error-hook*");
+ sc->SHARP_HOOK = mk_symbol(sc, "*sharp-hook*");
+#if USE_COMPILE_HOOK
+ sc->COMPILE_HOOK = mk_symbol(sc, "*compile-hook*");
+#endif
+
+ return !sc->no_memory;
+}
+
+void scheme_set_input_port_file(scheme *sc, FILE *fin) {
+ sc->inport=port_from_file(sc,fin,port_input);
+}
+
+void scheme_set_input_port_string(scheme *sc, char *start, char *past_the_end) {
+ sc->inport=port_from_string(sc,start,past_the_end,port_input);
+}
+
+void scheme_set_output_port_file(scheme *sc, FILE *fout) {
+ sc->outport=port_from_file(sc,fout,port_output);
+}
+
+void scheme_set_output_port_string(scheme *sc, char *start, char *past_the_end) {
+ sc->outport=port_from_string(sc,start,past_the_end,port_output);
+}
+
+void scheme_set_external_data(scheme *sc, void *p) {
+ sc->ext_data=p;
+}
+
+void scheme_deinit(scheme *sc) {
+ struct cell_segment *s;
+ int i;
+
+ sc->oblist=sc->NIL;
+ sc->global_env=sc->NIL;
+ dump_stack_free(sc);
+ sc->envir=sc->NIL;
+ sc->code=sc->NIL;
+ history_free(sc);
+ sc->args=sc->NIL;
+ sc->value=sc->NIL;
+ if(is_port(sc->inport)) {
+ typeflag(sc->inport) = T_ATOM;
+ }
+ sc->inport=sc->NIL;
+ sc->outport=sc->NIL;
+ if(is_port(sc->save_inport)) {
+ typeflag(sc->save_inport) = T_ATOM;
+ }
+ sc->save_inport=sc->NIL;
+ if(is_port(sc->loadport)) {
+ typeflag(sc->loadport) = T_ATOM;
+ }
+ sc->loadport=sc->NIL;
+
+ for(i=0; i<=sc->file_i; i++) {
+ port_clear_location(sc, &sc->load_stack[i]);
+ }
+
+ sc->gc_verbose=0;
+ gc(sc,sc->NIL,sc->NIL);
+
+ for (s = sc->cell_segments; s; s = _dealloc_cellseg(sc, s)) {
+ /* nop */
+ }
+ sc->free(sc->strbuff);
+}
+
+void scheme_load_file(scheme *sc, FILE *fin)
+{ scheme_load_named_file(sc,fin,0); }
+
+void scheme_load_named_file(scheme *sc, FILE *fin, const char *filename) {
+ dump_stack_reset(sc);
+ sc->envir = sc->global_env;
+ sc->file_i=0;
+ sc->load_stack[0].kind=port_input|port_file;
+ sc->load_stack[0].rep.stdio.file=fin;
+ sc->loadport=mk_port(sc,sc->load_stack);
+ sc->retcode=0;
+ if(fin==stdin) {
+ sc->interactive_repl=1;
+ }
+
+ port_init_location(sc, &sc->load_stack[0],
+ (fin != stdin && filename)
+ ? mk_string(sc, filename)
+ : NULL);
+
+ sc->inport=sc->loadport;
+ sc->args = mk_integer(sc,sc->file_i);
+ Eval_Cycle(sc, OP_T0LVL);
+ typeflag(sc->loadport)=T_ATOM;
+ if(sc->retcode==0) {
+ sc->retcode=sc->nesting!=0;
+ }
+
+ port_clear_location(sc, &sc->load_stack[0]);
+}
+
+void scheme_load_string(scheme *sc, const char *cmd) {
+ scheme_load_memory(sc, cmd, strlen(cmd), NULL);
+}
+
+void scheme_load_memory(scheme *sc, const char *buf, size_t len, const char *filename) {
+ dump_stack_reset(sc);
+ sc->envir = sc->global_env;
+ sc->file_i=0;
+ sc->load_stack[0].kind=port_input|port_string;
+ sc->load_stack[0].rep.string.start = (char *) buf; /* This func respects const */
+ sc->load_stack[0].rep.string.past_the_end = (char *) buf + len;
+ sc->load_stack[0].rep.string.curr = (char *) buf;
+ port_init_location(sc, &sc->load_stack[0], filename ? mk_string(sc, filename) : NULL);
+ sc->loadport=mk_port(sc,sc->load_stack);
+ sc->retcode=0;
+ sc->interactive_repl=0;
+ sc->inport=sc->loadport;
+ sc->args = mk_integer(sc,sc->file_i);
+ Eval_Cycle(sc, OP_T0LVL);
+ typeflag(sc->loadport)=T_ATOM;
+ if(sc->retcode==0) {
+ sc->retcode=sc->nesting!=0;
+ }
+
+ port_clear_location(sc, &sc->load_stack[0]);
+}
+
+void scheme_define(scheme *sc, pointer envir, pointer symbol, pointer value) {
+ pointer x;
+ pointer *sslot;
+ x = find_slot_spec_in_env(sc, envir, symbol, 0, &sslot);
+ if (x != sc->NIL) {
+ set_slot_in_env(sc, x, value);
+ } else {
+ new_slot_spec_in_env(sc, symbol, value, sslot);
+ }
+}
+
+#if !STANDALONE
+void scheme_register_foreign_func(scheme * sc, scheme_registerable * sr)
+{
+ scheme_define(sc,
+ sc->global_env,
+ mk_symbol(sc,sr->name),
+ mk_foreign_func(sc, sr->f));
+}
+
+void scheme_register_foreign_func_list(scheme * sc,
+ scheme_registerable * list,
+ int count)
+{
+ int i;
+ for(i = 0; i < count; i++)
+ {
+ scheme_register_foreign_func(sc, list + i);
+ }
+}
+
+pointer scheme_apply0(scheme *sc, const char *procname)
+{ return scheme_eval(sc, cons(sc,mk_symbol(sc,procname),sc->NIL)); }
+
+void save_from_C_call(scheme *sc)
+{
+ pointer saved_data =
+ cons(sc,
+ car(sc->sink),
+ cons(sc,
+ sc->envir,
+ sc->dump));
+ /* Push */
+ sc->c_nest = cons(sc, saved_data, sc->c_nest);
+ /* Truncate the dump stack so TS will return here when done, not
+ directly resume pre-C-call operations. */
+ dump_stack_reset(sc);
+}
+void restore_from_C_call(scheme *sc)
+{
+ car(sc->sink) = caar(sc->c_nest);
+ sc->envir = cadar(sc->c_nest);
+ sc->dump = cdr(cdar(sc->c_nest));
+ /* Pop */
+ sc->c_nest = cdr(sc->c_nest);
+}
+
+/* "func" and "args" are assumed to be already eval'ed. */
+pointer scheme_call(scheme *sc, pointer func, pointer args)
+{
+ int old_repl = sc->interactive_repl;
+ sc->interactive_repl = 0;
+ save_from_C_call(sc);
+ sc->envir = sc->global_env;
+ sc->args = args;
+ sc->code = func;
+ sc->retcode = 0;
+ Eval_Cycle(sc, OP_APPLY);
+ sc->interactive_repl = old_repl;
+ restore_from_C_call(sc);
+ return sc->value;
+}
+
+pointer scheme_eval(scheme *sc, pointer obj)
+{
+ int old_repl = sc->interactive_repl;
+ sc->interactive_repl = 0;
+ save_from_C_call(sc);
+ sc->args = sc->NIL;
+ sc->code = obj;
+ sc->retcode = 0;
+ Eval_Cycle(sc, OP_EVAL);
+ sc->interactive_repl = old_repl;
+ restore_from_C_call(sc);
+ return sc->value;
+}
+
+
+#endif
+
+/* ========== Main ========== */
+
+#if STANDALONE
+
+#if defined(__APPLE__) && !defined (OSX)
+int main()
+{
+ extern MacTS_main(int argc, char **argv);
+ char** argv;
+ int argc = ccommand(&argv);
+ MacTS_main(argc,argv);
+ return 0;
+}
+int MacTS_main(int argc, char **argv) {
+#else
+int main(int argc, char **argv) {
+#endif
+ scheme sc;
+ FILE *fin;
+ char *file_name=InitFile;
+ int retcode;
+ int isfile=1;
+
+ if(argc==1) {
+ printf(banner);
+ }
+ if(argc==2 && strcmp(argv[1],"-?")==0) {
+ printf("Usage: tinyscheme -?\n");
+ printf("or: tinyscheme [<file1> <file2> ...]\n");
+ printf("followed by\n");
+ printf(" -1 <file> [<arg1> <arg2> ...]\n");
+ printf(" -c <Scheme commands> [<arg1> <arg2> ...]\n");
+ printf("assuming that the executable is named tinyscheme.\n");
+ printf("Use - as filename for stdin.\n");
+ return 1;
+ }
+ if(!scheme_init(&sc)) {
+ fprintf(stderr,"Could not initialize!\n");
+ return 2;
+ }
+ scheme_set_input_port_file(&sc, stdin);
+ scheme_set_output_port_file(&sc, stdout);
+#if USE_DL
+ scheme_define(&sc,sc.global_env,mk_symbol(&sc,"load-extension"),mk_foreign_func(&sc, scm_load_ext));
+#endif
+ argv++;
+ if(access(file_name,0)!=0) {
+ char *p=getenv("TINYSCHEMEINIT");
+ if(p!=0) {
+ file_name=p;
+ }
+ }
+ do {
+ if(strcmp(file_name,"-")==0) {
+ fin=stdin;
+ } else if(strcmp(file_name,"-1")==0 || strcmp(file_name,"-c")==0) {
+ pointer args=sc.NIL;
+ isfile=file_name[1]=='1';
+ file_name=*argv++;
+ if(strcmp(file_name,"-")==0) {
+ fin=stdin;
+ } else if(isfile) {
+ fin=fopen(file_name,"r");
+ }
+ for(;*argv;argv++) {
+ pointer value=mk_string(&sc,*argv);
+ args=cons(&sc,value,args);
+ }
+ args=reverse_in_place(&sc,sc.NIL,args);
+ scheme_define(&sc,sc.global_env,mk_symbol(&sc,"*args*"),args);
+
+ } else {
+ fin=fopen(file_name,"r");
+ }
+ if(isfile && fin==0) {
+ fprintf(stderr,"Could not open file %s\n",file_name);
+ } else {
+ if(isfile) {
+ scheme_load_named_file(&sc,fin,file_name);
+ } else {
+ scheme_load_string(&sc,file_name);
+ }
+ if(!isfile || fin!=stdin) {
+ if(sc.retcode!=0) {
+ fprintf(stderr,"Errors encountered reading %s\n",file_name);
+ }
+ if(isfile) {
+ fclose(fin);
+ }
+ }
+ }
+ file_name=*argv++;
+ } while(file_name!=0);
+ if(argc==1) {
+ scheme_load_named_file(&sc,stdin,0);
+ }
+ retcode=sc.retcode;
+ scheme_deinit(&sc);
+
+ return retcode;
+}
+
+#endif
+
+/*
+Local variables:
+c-file-style: "k&r"
+End:
+*/
diff --git a/tests/gpgscm/scheme.h b/tests/gpgscm/scheme.h
new file mode 100644
index 0000000..6f917da
--- /dev/null
+++ b/tests/gpgscm/scheme.h
@@ -0,0 +1,290 @@
+/* SCHEME.H */
+
+#ifndef _SCHEME_H
+#define _SCHEME_H
+
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Default values for #define'd symbols
+ */
+#ifndef STANDALONE /* If used as standalone interpreter */
+# define STANDALONE 1
+#endif
+
+#ifndef _MSC_VER
+# define USE_STRCASECMP 1
+# ifndef USE_STRLWR
+# define USE_STRLWR 1
+# endif
+# define SCHEME_EXPORT
+#else
+# define USE_STRCASECMP 0
+# define USE_STRLWR 0
+# ifdef _SCHEME_SOURCE
+# define SCHEME_EXPORT __declspec(dllexport)
+# else
+# define SCHEME_EXPORT __declspec(dllimport)
+# endif
+#endif
+
+#if USE_NO_FEATURES
+# define USE_MATH 0
+# define USE_CHAR_CLASSIFIERS 0
+# define USE_ASCII_NAMES 0
+# define USE_STRING_PORTS 0
+# define USE_ERROR_HOOK 0
+# define USE_TRACING 0
+# define USE_COLON_HOOK 0
+# define USE_COMPILE_HOOK 0
+# define USE_DL 0
+# define USE_PLIST 0
+# define USE_SMALL_INTEGERS 0
+# define USE_HISTORY 0
+#endif
+
+
+#if USE_DL
+# define USE_INTERFACE 1
+#endif
+
+
+#ifndef USE_MATH /* If math support is needed */
+# define USE_MATH 1
+#endif
+
+#ifndef USE_CHAR_CLASSIFIERS /* If char classifiers are needed */
+# define USE_CHAR_CLASSIFIERS 1
+#endif
+
+#ifndef USE_ASCII_NAMES /* If extended escaped characters are needed */
+# define USE_ASCII_NAMES 1
+#endif
+
+#ifndef USE_STRING_PORTS /* Enable string ports */
+# define USE_STRING_PORTS 1
+#endif
+
+#ifndef USE_TRACING
+# define USE_TRACING 1
+#endif
+
+#ifndef USE_PLIST
+# define USE_PLIST 0
+#endif
+
+/* Keep a history of function calls. This enables a feature similar
+ * to stack traces. */
+#ifndef USE_HISTORY
+# define USE_HISTORY 1
+#endif
+
+/* To force system errors through user-defined error handling (see *error-hook*) */
+#ifndef USE_ERROR_HOOK
+# define USE_ERROR_HOOK 1
+#endif
+
+#ifndef USE_COLON_HOOK /* Enable qualified qualifier */
+# define USE_COLON_HOOK 1
+#endif
+
+/* Compile functions using *compile-hook*. The default hook expands
+ * macros. */
+#ifndef USE_COMPILE_HOOK
+# define USE_COMPILE_HOOK 1
+#endif
+
+/* Enable faster opcode dispatch. */
+#ifndef USE_THREADED_CODE
+# define USE_THREADED_CODE 1
+#endif
+
+/* Use a static set of cells to represent small numbers. This set
+ * notably includes all opcodes, and hence saves a cell reservation
+ * during 's_save'. */
+#ifndef USE_SMALL_INTEGERS
+# define USE_SMALL_INTEGERS 1
+#endif
+
+#ifndef USE_STRCASECMP /* stricmp for Unix */
+# define USE_STRCASECMP 0
+#endif
+
+#ifndef USE_STRLWR
+# define USE_STRLWR 1
+#endif
+
+#ifndef STDIO_ADDS_CR /* Define if DOS/Windows */
+# define STDIO_ADDS_CR 0
+#endif
+
+#ifndef INLINE
+# define INLINE
+#endif
+
+#ifndef USE_INTERFACE
+# define USE_INTERFACE 0
+#endif
+
+#ifndef SHOW_ERROR_LINE /* Show error line in file */
+# define SHOW_ERROR_LINE 1
+#endif
+
+typedef struct scheme scheme;
+typedef struct cell *pointer;
+
+typedef void * (*func_alloc)(size_t);
+typedef void (*func_dealloc)(void *);
+
+/* table of functions required for foreign objects */
+typedef struct foreign_object_vtable {
+ void (*finalize)(scheme *sc, void *data);
+ void (*to_string)(scheme *sc, char *out, size_t size, void *data);
+} foreign_object_vtable;
+
+/* num, for generic arithmetic */
+typedef struct num {
+ char is_fixnum;
+ union {
+ long ivalue;
+ double rvalue;
+ } value;
+} num;
+
+SCHEME_EXPORT scheme *scheme_init_new(void);
+SCHEME_EXPORT scheme *scheme_init_new_custom_alloc(func_alloc malloc, func_dealloc free);
+SCHEME_EXPORT int scheme_init(scheme *sc);
+SCHEME_EXPORT int scheme_init_custom_alloc(scheme *sc, func_alloc, func_dealloc);
+SCHEME_EXPORT void scheme_deinit(scheme *sc);
+void scheme_set_input_port_file(scheme *sc, FILE *fin);
+void scheme_set_input_port_string(scheme *sc, char *start, char *past_the_end);
+SCHEME_EXPORT void scheme_set_output_port_file(scheme *sc, FILE *fin);
+void scheme_set_output_port_string(scheme *sc, char *start, char *past_the_end);
+SCHEME_EXPORT void scheme_load_file(scheme *sc, FILE *fin);
+SCHEME_EXPORT void scheme_load_named_file(scheme *sc, FILE *fin, const char *filename);
+SCHEME_EXPORT void scheme_load_string(scheme *sc, const char *cmd);
+SCHEME_EXPORT void scheme_load_memory(scheme *sc, const char *buf, size_t len,
+ const char *filename);
+SCHEME_EXPORT pointer scheme_apply0(scheme *sc, const char *procname);
+SCHEME_EXPORT pointer scheme_call(scheme *sc, pointer func, pointer args);
+SCHEME_EXPORT pointer scheme_eval(scheme *sc, pointer obj);
+void scheme_set_external_data(scheme *sc, void *p);
+SCHEME_EXPORT void scheme_define(scheme *sc, pointer env, pointer symbol, pointer value);
+
+typedef pointer (*foreign_func)(scheme *, pointer);
+
+pointer _cons(scheme *sc, pointer a, pointer b, int immutable);
+pointer mk_integer(scheme *sc, long num);
+pointer mk_real(scheme *sc, double num);
+pointer mk_symbol(scheme *sc, const char *name);
+pointer gensym(scheme *sc);
+pointer mk_string(scheme *sc, const char *str);
+pointer mk_counted_string(scheme *sc, const char *str, int len);
+pointer mk_empty_string(scheme *sc, int len, char fill);
+pointer mk_character(scheme *sc, int c);
+pointer mk_foreign_func(scheme *sc, foreign_func f);
+pointer mk_foreign_object(scheme *sc, const foreign_object_vtable *vtable, void *data);
+void putstr(scheme *sc, const char *s);
+int list_length(scheme *sc, pointer a);
+int eqv(pointer a, pointer b);
+
+
+#if USE_INTERFACE
+struct scheme_interface {
+ void (*scheme_define)(scheme *sc, pointer env, pointer symbol, pointer value);
+ pointer (*cons)(scheme *sc, pointer a, pointer b);
+ pointer (*immutable_cons)(scheme *sc, pointer a, pointer b);
+ pointer (*reserve_cells)(scheme *sc, int n);
+ pointer (*mk_integer)(scheme *sc, long num);
+ pointer (*mk_real)(scheme *sc, double num);
+ pointer (*mk_symbol)(scheme *sc, const char *name);
+ pointer (*gensym)(scheme *sc);
+ pointer (*mk_string)(scheme *sc, const char *str);
+ pointer (*mk_counted_string)(scheme *sc, const char *str, int len);
+ pointer (*mk_character)(scheme *sc, int c);
+ pointer (*mk_vector)(scheme *sc, int len);
+ pointer (*mk_foreign_func)(scheme *sc, foreign_func f);
+ pointer (*mk_foreign_object)(scheme *sc, const foreign_object_vtable *vtable, void *data);
+ const foreign_object_vtable *(*get_foreign_object_vtable)(pointer p);
+ void *(*get_foreign_object_data)(pointer p);
+ void (*putstr)(scheme *sc, const char *s);
+ void (*putcharacter)(scheme *sc, int c);
+
+ int (*is_string)(pointer p);
+ char *(*string_value)(pointer p);
+ int (*is_number)(pointer p);
+ num (*nvalue)(pointer p);
+ long (*ivalue)(pointer p);
+ double (*rvalue)(pointer p);
+ int (*is_integer)(pointer p);
+ int (*is_real)(pointer p);
+ int (*is_character)(pointer p);
+ long (*charvalue)(pointer p);
+ int (*is_list)(scheme *sc, pointer p);
+ int (*is_vector)(pointer p);
+ int (*list_length)(scheme *sc, pointer vec);
+ long (*vector_length)(pointer vec);
+ void (*fill_vector)(pointer vec, pointer elem);
+ pointer (*vector_elem)(pointer vec, int ielem);
+ pointer (*set_vector_elem)(pointer vec, int ielem, pointer newel);
+ int (*is_port)(pointer p);
+
+ int (*is_pair)(pointer p);
+ pointer (*pair_car)(pointer p);
+ pointer (*pair_cdr)(pointer p);
+ pointer (*set_car)(pointer p, pointer q);
+ pointer (*set_cdr)(pointer p, pointer q);
+
+ int (*is_symbol)(pointer p);
+ char *(*symname)(pointer p);
+
+ int (*is_syntax)(pointer p);
+ int (*is_proc)(pointer p);
+ int (*is_foreign)(pointer p);
+ char *(*syntaxname)(pointer p);
+ int (*is_closure)(pointer p);
+ int (*is_macro)(pointer p);
+ pointer (*closure_code)(pointer p);
+ pointer (*closure_env)(pointer p);
+
+ int (*is_continuation)(pointer p);
+ int (*is_promise)(pointer p);
+ int (*is_environment)(pointer p);
+ int (*is_immutable)(pointer p);
+ void (*setimmutable)(pointer p);
+ void (*load_file)(scheme *sc, FILE *fin);
+ void (*load_string)(scheme *sc, const char *input);
+ pointer (*mk_port_from_file)(scheme *sc, FILE *f, int kind);
+};
+#endif
+
+#if !STANDALONE
+typedef struct scheme_registerable
+{
+ foreign_func f;
+ const char * name;
+}
+scheme_registerable;
+
+void scheme_register_foreign_func_list(scheme * sc,
+ scheme_registerable * list,
+ int n);
+
+#endif /* !STANDALONE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+/*
+Local variables:
+c-file-style: "k&r"
+End:
+*/
diff --git a/tests/gpgscm/small-integers.h b/tests/gpgscm/small-integers.h
new file mode 100644
index 0000000..46eda34
--- /dev/null
+++ b/tests/gpgscm/small-integers.h
@@ -0,0 +1,847 @@
+/* Constant integer objects for TinySCHEME.
+ *
+ * Copyright (C) 2017 g10 code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Ohne Worte. Generated using:
+ *
+ * $ n=0; while read line ; do \
+ * echo "DEFINE_INTEGER($n)" ; \
+ * n="$(expr $n + 1)" ; \
+ * done <./init.scm >> small-integers.h
+ */
+
+DEFINE_INTEGER(0)
+DEFINE_INTEGER(1)
+DEFINE_INTEGER(2)
+DEFINE_INTEGER(3)
+DEFINE_INTEGER(4)
+DEFINE_INTEGER(5)
+DEFINE_INTEGER(6)
+DEFINE_INTEGER(7)
+DEFINE_INTEGER(8)
+DEFINE_INTEGER(9)
+DEFINE_INTEGER(10)
+DEFINE_INTEGER(11)
+DEFINE_INTEGER(12)
+DEFINE_INTEGER(13)
+DEFINE_INTEGER(14)
+DEFINE_INTEGER(15)
+DEFINE_INTEGER(16)
+DEFINE_INTEGER(17)
+DEFINE_INTEGER(18)
+DEFINE_INTEGER(19)
+DEFINE_INTEGER(20)
+DEFINE_INTEGER(21)
+DEFINE_INTEGER(22)
+DEFINE_INTEGER(23)
+DEFINE_INTEGER(24)
+DEFINE_INTEGER(25)
+DEFINE_INTEGER(26)
+DEFINE_INTEGER(27)
+DEFINE_INTEGER(28)
+DEFINE_INTEGER(29)
+DEFINE_INTEGER(30)
+DEFINE_INTEGER(31)
+DEFINE_INTEGER(32)
+DEFINE_INTEGER(33)
+DEFINE_INTEGER(34)
+DEFINE_INTEGER(35)
+DEFINE_INTEGER(36)
+DEFINE_INTEGER(37)
+DEFINE_INTEGER(38)
+DEFINE_INTEGER(39)
+DEFINE_INTEGER(40)
+DEFINE_INTEGER(41)
+DEFINE_INTEGER(42)
+DEFINE_INTEGER(43)
+DEFINE_INTEGER(44)
+DEFINE_INTEGER(45)
+DEFINE_INTEGER(46)
+DEFINE_INTEGER(47)
+DEFINE_INTEGER(48)
+DEFINE_INTEGER(49)
+DEFINE_INTEGER(50)
+DEFINE_INTEGER(51)
+DEFINE_INTEGER(52)
+DEFINE_INTEGER(53)
+DEFINE_INTEGER(54)
+DEFINE_INTEGER(55)
+DEFINE_INTEGER(56)
+DEFINE_INTEGER(57)
+DEFINE_INTEGER(58)
+DEFINE_INTEGER(59)
+DEFINE_INTEGER(60)
+DEFINE_INTEGER(61)
+DEFINE_INTEGER(62)
+DEFINE_INTEGER(63)
+DEFINE_INTEGER(64)
+DEFINE_INTEGER(65)
+DEFINE_INTEGER(66)
+DEFINE_INTEGER(67)
+DEFINE_INTEGER(68)
+DEFINE_INTEGER(69)
+DEFINE_INTEGER(70)
+DEFINE_INTEGER(71)
+DEFINE_INTEGER(72)
+DEFINE_INTEGER(73)
+DEFINE_INTEGER(74)
+DEFINE_INTEGER(75)
+DEFINE_INTEGER(76)
+DEFINE_INTEGER(77)
+DEFINE_INTEGER(78)
+DEFINE_INTEGER(79)
+DEFINE_INTEGER(80)
+DEFINE_INTEGER(81)
+DEFINE_INTEGER(82)
+DEFINE_INTEGER(83)
+DEFINE_INTEGER(84)
+DEFINE_INTEGER(85)
+DEFINE_INTEGER(86)
+DEFINE_INTEGER(87)
+DEFINE_INTEGER(88)
+DEFINE_INTEGER(89)
+DEFINE_INTEGER(90)
+DEFINE_INTEGER(91)
+DEFINE_INTEGER(92)
+DEFINE_INTEGER(93)
+DEFINE_INTEGER(94)
+DEFINE_INTEGER(95)
+DEFINE_INTEGER(96)
+DEFINE_INTEGER(97)
+DEFINE_INTEGER(98)
+DEFINE_INTEGER(99)
+DEFINE_INTEGER(100)
+DEFINE_INTEGER(101)
+DEFINE_INTEGER(102)
+DEFINE_INTEGER(103)
+DEFINE_INTEGER(104)
+DEFINE_INTEGER(105)
+DEFINE_INTEGER(106)
+DEFINE_INTEGER(107)
+DEFINE_INTEGER(108)
+DEFINE_INTEGER(109)
+DEFINE_INTEGER(110)
+DEFINE_INTEGER(111)
+DEFINE_INTEGER(112)
+DEFINE_INTEGER(113)
+DEFINE_INTEGER(114)
+DEFINE_INTEGER(115)
+DEFINE_INTEGER(116)
+DEFINE_INTEGER(117)
+DEFINE_INTEGER(118)
+DEFINE_INTEGER(119)
+DEFINE_INTEGER(120)
+DEFINE_INTEGER(121)
+DEFINE_INTEGER(122)
+DEFINE_INTEGER(123)
+DEFINE_INTEGER(124)
+DEFINE_INTEGER(125)
+DEFINE_INTEGER(126)
+DEFINE_INTEGER(127)
+DEFINE_INTEGER(128)
+DEFINE_INTEGER(129)
+DEFINE_INTEGER(130)
+DEFINE_INTEGER(131)
+DEFINE_INTEGER(132)
+DEFINE_INTEGER(133)
+DEFINE_INTEGER(134)
+DEFINE_INTEGER(135)
+DEFINE_INTEGER(136)
+DEFINE_INTEGER(137)
+DEFINE_INTEGER(138)
+DEFINE_INTEGER(139)
+DEFINE_INTEGER(140)
+DEFINE_INTEGER(141)
+DEFINE_INTEGER(142)
+DEFINE_INTEGER(143)
+DEFINE_INTEGER(144)
+DEFINE_INTEGER(145)
+DEFINE_INTEGER(146)
+DEFINE_INTEGER(147)
+DEFINE_INTEGER(148)
+DEFINE_INTEGER(149)
+DEFINE_INTEGER(150)
+DEFINE_INTEGER(151)
+DEFINE_INTEGER(152)
+DEFINE_INTEGER(153)
+DEFINE_INTEGER(154)
+DEFINE_INTEGER(155)
+DEFINE_INTEGER(156)
+DEFINE_INTEGER(157)
+DEFINE_INTEGER(158)
+DEFINE_INTEGER(159)
+DEFINE_INTEGER(160)
+DEFINE_INTEGER(161)
+DEFINE_INTEGER(162)
+DEFINE_INTEGER(163)
+DEFINE_INTEGER(164)
+DEFINE_INTEGER(165)
+DEFINE_INTEGER(166)
+DEFINE_INTEGER(167)
+DEFINE_INTEGER(168)
+DEFINE_INTEGER(169)
+DEFINE_INTEGER(170)
+DEFINE_INTEGER(171)
+DEFINE_INTEGER(172)
+DEFINE_INTEGER(173)
+DEFINE_INTEGER(174)
+DEFINE_INTEGER(175)
+DEFINE_INTEGER(176)
+DEFINE_INTEGER(177)
+DEFINE_INTEGER(178)
+DEFINE_INTEGER(179)
+DEFINE_INTEGER(180)
+DEFINE_INTEGER(181)
+DEFINE_INTEGER(182)
+DEFINE_INTEGER(183)
+DEFINE_INTEGER(184)
+DEFINE_INTEGER(185)
+DEFINE_INTEGER(186)
+DEFINE_INTEGER(187)
+DEFINE_INTEGER(188)
+DEFINE_INTEGER(189)
+DEFINE_INTEGER(190)
+DEFINE_INTEGER(191)
+DEFINE_INTEGER(192)
+DEFINE_INTEGER(193)
+DEFINE_INTEGER(194)
+DEFINE_INTEGER(195)
+DEFINE_INTEGER(196)
+DEFINE_INTEGER(197)
+DEFINE_INTEGER(198)
+DEFINE_INTEGER(199)
+DEFINE_INTEGER(200)
+DEFINE_INTEGER(201)
+DEFINE_INTEGER(202)
+DEFINE_INTEGER(203)
+DEFINE_INTEGER(204)
+DEFINE_INTEGER(205)
+DEFINE_INTEGER(206)
+DEFINE_INTEGER(207)
+DEFINE_INTEGER(208)
+DEFINE_INTEGER(209)
+DEFINE_INTEGER(210)
+DEFINE_INTEGER(211)
+DEFINE_INTEGER(212)
+DEFINE_INTEGER(213)
+DEFINE_INTEGER(214)
+DEFINE_INTEGER(215)
+DEFINE_INTEGER(216)
+DEFINE_INTEGER(217)
+DEFINE_INTEGER(218)
+DEFINE_INTEGER(219)
+DEFINE_INTEGER(220)
+DEFINE_INTEGER(221)
+DEFINE_INTEGER(222)
+DEFINE_INTEGER(223)
+DEFINE_INTEGER(224)
+DEFINE_INTEGER(225)
+DEFINE_INTEGER(226)
+DEFINE_INTEGER(227)
+DEFINE_INTEGER(228)
+DEFINE_INTEGER(229)
+DEFINE_INTEGER(230)
+DEFINE_INTEGER(231)
+DEFINE_INTEGER(232)
+DEFINE_INTEGER(233)
+DEFINE_INTEGER(234)
+DEFINE_INTEGER(235)
+DEFINE_INTEGER(236)
+DEFINE_INTEGER(237)
+DEFINE_INTEGER(238)
+DEFINE_INTEGER(239)
+DEFINE_INTEGER(240)
+DEFINE_INTEGER(241)
+DEFINE_INTEGER(242)
+DEFINE_INTEGER(243)
+DEFINE_INTEGER(244)
+DEFINE_INTEGER(245)
+DEFINE_INTEGER(246)
+DEFINE_INTEGER(247)
+DEFINE_INTEGER(248)
+DEFINE_INTEGER(249)
+DEFINE_INTEGER(250)
+DEFINE_INTEGER(251)
+DEFINE_INTEGER(252)
+DEFINE_INTEGER(253)
+DEFINE_INTEGER(254)
+DEFINE_INTEGER(255)
+DEFINE_INTEGER(256)
+DEFINE_INTEGER(257)
+DEFINE_INTEGER(258)
+DEFINE_INTEGER(259)
+DEFINE_INTEGER(260)
+DEFINE_INTEGER(261)
+DEFINE_INTEGER(262)
+DEFINE_INTEGER(263)
+DEFINE_INTEGER(264)
+DEFINE_INTEGER(265)
+DEFINE_INTEGER(266)
+DEFINE_INTEGER(267)
+DEFINE_INTEGER(268)
+DEFINE_INTEGER(269)
+DEFINE_INTEGER(270)
+DEFINE_INTEGER(271)
+DEFINE_INTEGER(272)
+DEFINE_INTEGER(273)
+DEFINE_INTEGER(274)
+DEFINE_INTEGER(275)
+DEFINE_INTEGER(276)
+DEFINE_INTEGER(277)
+DEFINE_INTEGER(278)
+DEFINE_INTEGER(279)
+DEFINE_INTEGER(280)
+DEFINE_INTEGER(281)
+DEFINE_INTEGER(282)
+DEFINE_INTEGER(283)
+DEFINE_INTEGER(284)
+DEFINE_INTEGER(285)
+DEFINE_INTEGER(286)
+DEFINE_INTEGER(287)
+DEFINE_INTEGER(288)
+DEFINE_INTEGER(289)
+DEFINE_INTEGER(290)
+DEFINE_INTEGER(291)
+DEFINE_INTEGER(292)
+DEFINE_INTEGER(293)
+DEFINE_INTEGER(294)
+DEFINE_INTEGER(295)
+DEFINE_INTEGER(296)
+DEFINE_INTEGER(297)
+DEFINE_INTEGER(298)
+DEFINE_INTEGER(299)
+DEFINE_INTEGER(300)
+DEFINE_INTEGER(301)
+DEFINE_INTEGER(302)
+DEFINE_INTEGER(303)
+DEFINE_INTEGER(304)
+DEFINE_INTEGER(305)
+DEFINE_INTEGER(306)
+DEFINE_INTEGER(307)
+DEFINE_INTEGER(308)
+DEFINE_INTEGER(309)
+DEFINE_INTEGER(310)
+DEFINE_INTEGER(311)
+DEFINE_INTEGER(312)
+DEFINE_INTEGER(313)
+DEFINE_INTEGER(314)
+DEFINE_INTEGER(315)
+DEFINE_INTEGER(316)
+DEFINE_INTEGER(317)
+DEFINE_INTEGER(318)
+DEFINE_INTEGER(319)
+DEFINE_INTEGER(320)
+DEFINE_INTEGER(321)
+DEFINE_INTEGER(322)
+DEFINE_INTEGER(323)
+DEFINE_INTEGER(324)
+DEFINE_INTEGER(325)
+DEFINE_INTEGER(326)
+DEFINE_INTEGER(327)
+DEFINE_INTEGER(328)
+DEFINE_INTEGER(329)
+DEFINE_INTEGER(330)
+DEFINE_INTEGER(331)
+DEFINE_INTEGER(332)
+DEFINE_INTEGER(333)
+DEFINE_INTEGER(334)
+DEFINE_INTEGER(335)
+DEFINE_INTEGER(336)
+DEFINE_INTEGER(337)
+DEFINE_INTEGER(338)
+DEFINE_INTEGER(339)
+DEFINE_INTEGER(340)
+DEFINE_INTEGER(341)
+DEFINE_INTEGER(342)
+DEFINE_INTEGER(343)
+DEFINE_INTEGER(344)
+DEFINE_INTEGER(345)
+DEFINE_INTEGER(346)
+DEFINE_INTEGER(347)
+DEFINE_INTEGER(348)
+DEFINE_INTEGER(349)
+DEFINE_INTEGER(350)
+DEFINE_INTEGER(351)
+DEFINE_INTEGER(352)
+DEFINE_INTEGER(353)
+DEFINE_INTEGER(354)
+DEFINE_INTEGER(355)
+DEFINE_INTEGER(356)
+DEFINE_INTEGER(357)
+DEFINE_INTEGER(358)
+DEFINE_INTEGER(359)
+DEFINE_INTEGER(360)
+DEFINE_INTEGER(361)
+DEFINE_INTEGER(362)
+DEFINE_INTEGER(363)
+DEFINE_INTEGER(364)
+DEFINE_INTEGER(365)
+DEFINE_INTEGER(366)
+DEFINE_INTEGER(367)
+DEFINE_INTEGER(368)
+DEFINE_INTEGER(369)
+DEFINE_INTEGER(370)
+DEFINE_INTEGER(371)
+DEFINE_INTEGER(372)
+DEFINE_INTEGER(373)
+DEFINE_INTEGER(374)
+DEFINE_INTEGER(375)
+DEFINE_INTEGER(376)
+DEFINE_INTEGER(377)
+DEFINE_INTEGER(378)
+DEFINE_INTEGER(379)
+DEFINE_INTEGER(380)
+DEFINE_INTEGER(381)
+DEFINE_INTEGER(382)
+DEFINE_INTEGER(383)
+DEFINE_INTEGER(384)
+DEFINE_INTEGER(385)
+DEFINE_INTEGER(386)
+DEFINE_INTEGER(387)
+DEFINE_INTEGER(388)
+DEFINE_INTEGER(389)
+DEFINE_INTEGER(390)
+DEFINE_INTEGER(391)
+DEFINE_INTEGER(392)
+DEFINE_INTEGER(393)
+DEFINE_INTEGER(394)
+DEFINE_INTEGER(395)
+DEFINE_INTEGER(396)
+DEFINE_INTEGER(397)
+DEFINE_INTEGER(398)
+DEFINE_INTEGER(399)
+DEFINE_INTEGER(400)
+DEFINE_INTEGER(401)
+DEFINE_INTEGER(402)
+DEFINE_INTEGER(403)
+DEFINE_INTEGER(404)
+DEFINE_INTEGER(405)
+DEFINE_INTEGER(406)
+DEFINE_INTEGER(407)
+DEFINE_INTEGER(408)
+DEFINE_INTEGER(409)
+DEFINE_INTEGER(410)
+DEFINE_INTEGER(411)
+DEFINE_INTEGER(412)
+DEFINE_INTEGER(413)
+DEFINE_INTEGER(414)
+DEFINE_INTEGER(415)
+DEFINE_INTEGER(416)
+DEFINE_INTEGER(417)
+DEFINE_INTEGER(418)
+DEFINE_INTEGER(419)
+DEFINE_INTEGER(420)
+DEFINE_INTEGER(421)
+DEFINE_INTEGER(422)
+DEFINE_INTEGER(423)
+DEFINE_INTEGER(424)
+DEFINE_INTEGER(425)
+DEFINE_INTEGER(426)
+DEFINE_INTEGER(427)
+DEFINE_INTEGER(428)
+DEFINE_INTEGER(429)
+DEFINE_INTEGER(430)
+DEFINE_INTEGER(431)
+DEFINE_INTEGER(432)
+DEFINE_INTEGER(433)
+DEFINE_INTEGER(434)
+DEFINE_INTEGER(435)
+DEFINE_INTEGER(436)
+DEFINE_INTEGER(437)
+DEFINE_INTEGER(438)
+DEFINE_INTEGER(439)
+DEFINE_INTEGER(440)
+DEFINE_INTEGER(441)
+DEFINE_INTEGER(442)
+DEFINE_INTEGER(443)
+DEFINE_INTEGER(444)
+DEFINE_INTEGER(445)
+DEFINE_INTEGER(446)
+DEFINE_INTEGER(447)
+DEFINE_INTEGER(448)
+DEFINE_INTEGER(449)
+DEFINE_INTEGER(450)
+DEFINE_INTEGER(451)
+DEFINE_INTEGER(452)
+DEFINE_INTEGER(453)
+DEFINE_INTEGER(454)
+DEFINE_INTEGER(455)
+DEFINE_INTEGER(456)
+DEFINE_INTEGER(457)
+DEFINE_INTEGER(458)
+DEFINE_INTEGER(459)
+DEFINE_INTEGER(460)
+DEFINE_INTEGER(461)
+DEFINE_INTEGER(462)
+DEFINE_INTEGER(463)
+DEFINE_INTEGER(464)
+DEFINE_INTEGER(465)
+DEFINE_INTEGER(466)
+DEFINE_INTEGER(467)
+DEFINE_INTEGER(468)
+DEFINE_INTEGER(469)
+DEFINE_INTEGER(470)
+DEFINE_INTEGER(471)
+DEFINE_INTEGER(472)
+DEFINE_INTEGER(473)
+DEFINE_INTEGER(474)
+DEFINE_INTEGER(475)
+DEFINE_INTEGER(476)
+DEFINE_INTEGER(477)
+DEFINE_INTEGER(478)
+DEFINE_INTEGER(479)
+DEFINE_INTEGER(480)
+DEFINE_INTEGER(481)
+DEFINE_INTEGER(482)
+DEFINE_INTEGER(483)
+DEFINE_INTEGER(484)
+DEFINE_INTEGER(485)
+DEFINE_INTEGER(486)
+DEFINE_INTEGER(487)
+DEFINE_INTEGER(488)
+DEFINE_INTEGER(489)
+DEFINE_INTEGER(490)
+DEFINE_INTEGER(491)
+DEFINE_INTEGER(492)
+DEFINE_INTEGER(493)
+DEFINE_INTEGER(494)
+DEFINE_INTEGER(495)
+DEFINE_INTEGER(496)
+DEFINE_INTEGER(497)
+DEFINE_INTEGER(498)
+DEFINE_INTEGER(499)
+DEFINE_INTEGER(500)
+DEFINE_INTEGER(501)
+DEFINE_INTEGER(502)
+DEFINE_INTEGER(503)
+DEFINE_INTEGER(504)
+DEFINE_INTEGER(505)
+DEFINE_INTEGER(506)
+DEFINE_INTEGER(507)
+DEFINE_INTEGER(508)
+DEFINE_INTEGER(509)
+DEFINE_INTEGER(510)
+DEFINE_INTEGER(511)
+DEFINE_INTEGER(512)
+DEFINE_INTEGER(513)
+DEFINE_INTEGER(514)
+DEFINE_INTEGER(515)
+DEFINE_INTEGER(516)
+DEFINE_INTEGER(517)
+DEFINE_INTEGER(518)
+DEFINE_INTEGER(519)
+DEFINE_INTEGER(520)
+DEFINE_INTEGER(521)
+DEFINE_INTEGER(522)
+DEFINE_INTEGER(523)
+DEFINE_INTEGER(524)
+DEFINE_INTEGER(525)
+DEFINE_INTEGER(526)
+DEFINE_INTEGER(527)
+DEFINE_INTEGER(528)
+DEFINE_INTEGER(529)
+DEFINE_INTEGER(530)
+DEFINE_INTEGER(531)
+DEFINE_INTEGER(532)
+DEFINE_INTEGER(533)
+DEFINE_INTEGER(534)
+DEFINE_INTEGER(535)
+DEFINE_INTEGER(536)
+DEFINE_INTEGER(537)
+DEFINE_INTEGER(538)
+DEFINE_INTEGER(539)
+DEFINE_INTEGER(540)
+DEFINE_INTEGER(541)
+DEFINE_INTEGER(542)
+DEFINE_INTEGER(543)
+DEFINE_INTEGER(544)
+DEFINE_INTEGER(545)
+DEFINE_INTEGER(546)
+DEFINE_INTEGER(547)
+DEFINE_INTEGER(548)
+DEFINE_INTEGER(549)
+DEFINE_INTEGER(550)
+DEFINE_INTEGER(551)
+DEFINE_INTEGER(552)
+DEFINE_INTEGER(553)
+DEFINE_INTEGER(554)
+DEFINE_INTEGER(555)
+DEFINE_INTEGER(556)
+DEFINE_INTEGER(557)
+DEFINE_INTEGER(558)
+DEFINE_INTEGER(559)
+DEFINE_INTEGER(560)
+DEFINE_INTEGER(561)
+DEFINE_INTEGER(562)
+DEFINE_INTEGER(563)
+DEFINE_INTEGER(564)
+DEFINE_INTEGER(565)
+DEFINE_INTEGER(566)
+DEFINE_INTEGER(567)
+DEFINE_INTEGER(568)
+DEFINE_INTEGER(569)
+DEFINE_INTEGER(570)
+DEFINE_INTEGER(571)
+DEFINE_INTEGER(572)
+DEFINE_INTEGER(573)
+DEFINE_INTEGER(574)
+DEFINE_INTEGER(575)
+DEFINE_INTEGER(576)
+DEFINE_INTEGER(577)
+DEFINE_INTEGER(578)
+DEFINE_INTEGER(579)
+DEFINE_INTEGER(580)
+DEFINE_INTEGER(581)
+DEFINE_INTEGER(582)
+DEFINE_INTEGER(583)
+DEFINE_INTEGER(584)
+DEFINE_INTEGER(585)
+DEFINE_INTEGER(586)
+DEFINE_INTEGER(587)
+DEFINE_INTEGER(588)
+DEFINE_INTEGER(589)
+DEFINE_INTEGER(590)
+DEFINE_INTEGER(591)
+DEFINE_INTEGER(592)
+DEFINE_INTEGER(593)
+DEFINE_INTEGER(594)
+DEFINE_INTEGER(595)
+DEFINE_INTEGER(596)
+DEFINE_INTEGER(597)
+DEFINE_INTEGER(598)
+DEFINE_INTEGER(599)
+DEFINE_INTEGER(600)
+DEFINE_INTEGER(601)
+DEFINE_INTEGER(602)
+DEFINE_INTEGER(603)
+DEFINE_INTEGER(604)
+DEFINE_INTEGER(605)
+DEFINE_INTEGER(606)
+DEFINE_INTEGER(607)
+DEFINE_INTEGER(608)
+DEFINE_INTEGER(609)
+DEFINE_INTEGER(610)
+DEFINE_INTEGER(611)
+DEFINE_INTEGER(612)
+DEFINE_INTEGER(613)
+DEFINE_INTEGER(614)
+DEFINE_INTEGER(615)
+DEFINE_INTEGER(616)
+DEFINE_INTEGER(617)
+DEFINE_INTEGER(618)
+DEFINE_INTEGER(619)
+DEFINE_INTEGER(620)
+DEFINE_INTEGER(621)
+DEFINE_INTEGER(622)
+DEFINE_INTEGER(623)
+DEFINE_INTEGER(624)
+DEFINE_INTEGER(625)
+DEFINE_INTEGER(626)
+DEFINE_INTEGER(627)
+DEFINE_INTEGER(628)
+DEFINE_INTEGER(629)
+DEFINE_INTEGER(630)
+DEFINE_INTEGER(631)
+DEFINE_INTEGER(632)
+DEFINE_INTEGER(633)
+DEFINE_INTEGER(634)
+DEFINE_INTEGER(635)
+DEFINE_INTEGER(636)
+DEFINE_INTEGER(637)
+DEFINE_INTEGER(638)
+DEFINE_INTEGER(639)
+DEFINE_INTEGER(640)
+DEFINE_INTEGER(641)
+DEFINE_INTEGER(642)
+DEFINE_INTEGER(643)
+DEFINE_INTEGER(644)
+DEFINE_INTEGER(645)
+DEFINE_INTEGER(646)
+DEFINE_INTEGER(647)
+DEFINE_INTEGER(648)
+DEFINE_INTEGER(649)
+DEFINE_INTEGER(650)
+DEFINE_INTEGER(651)
+DEFINE_INTEGER(652)
+DEFINE_INTEGER(653)
+DEFINE_INTEGER(654)
+DEFINE_INTEGER(655)
+DEFINE_INTEGER(656)
+DEFINE_INTEGER(657)
+DEFINE_INTEGER(658)
+DEFINE_INTEGER(659)
+DEFINE_INTEGER(660)
+DEFINE_INTEGER(661)
+DEFINE_INTEGER(662)
+DEFINE_INTEGER(663)
+DEFINE_INTEGER(664)
+DEFINE_INTEGER(665)
+DEFINE_INTEGER(666)
+DEFINE_INTEGER(667)
+DEFINE_INTEGER(668)
+DEFINE_INTEGER(669)
+DEFINE_INTEGER(670)
+DEFINE_INTEGER(671)
+DEFINE_INTEGER(672)
+DEFINE_INTEGER(673)
+DEFINE_INTEGER(674)
+DEFINE_INTEGER(675)
+DEFINE_INTEGER(676)
+DEFINE_INTEGER(677)
+DEFINE_INTEGER(678)
+DEFINE_INTEGER(679)
+DEFINE_INTEGER(680)
+DEFINE_INTEGER(681)
+DEFINE_INTEGER(682)
+DEFINE_INTEGER(683)
+DEFINE_INTEGER(684)
+DEFINE_INTEGER(685)
+DEFINE_INTEGER(686)
+DEFINE_INTEGER(687)
+DEFINE_INTEGER(688)
+DEFINE_INTEGER(689)
+DEFINE_INTEGER(690)
+DEFINE_INTEGER(691)
+DEFINE_INTEGER(692)
+DEFINE_INTEGER(693)
+DEFINE_INTEGER(694)
+DEFINE_INTEGER(695)
+DEFINE_INTEGER(696)
+DEFINE_INTEGER(697)
+DEFINE_INTEGER(698)
+DEFINE_INTEGER(699)
+DEFINE_INTEGER(700)
+DEFINE_INTEGER(701)
+DEFINE_INTEGER(702)
+DEFINE_INTEGER(703)
+DEFINE_INTEGER(704)
+DEFINE_INTEGER(705)
+DEFINE_INTEGER(706)
+DEFINE_INTEGER(707)
+DEFINE_INTEGER(708)
+DEFINE_INTEGER(709)
+DEFINE_INTEGER(710)
+DEFINE_INTEGER(711)
+DEFINE_INTEGER(712)
+DEFINE_INTEGER(713)
+DEFINE_INTEGER(714)
+DEFINE_INTEGER(715)
+DEFINE_INTEGER(716)
+DEFINE_INTEGER(717)
+DEFINE_INTEGER(718)
+DEFINE_INTEGER(719)
+DEFINE_INTEGER(720)
+DEFINE_INTEGER(721)
+DEFINE_INTEGER(722)
+DEFINE_INTEGER(723)
+DEFINE_INTEGER(724)
+DEFINE_INTEGER(725)
+DEFINE_INTEGER(726)
+DEFINE_INTEGER(727)
+DEFINE_INTEGER(728)
+DEFINE_INTEGER(729)
+DEFINE_INTEGER(730)
+DEFINE_INTEGER(731)
+DEFINE_INTEGER(732)
+DEFINE_INTEGER(733)
+DEFINE_INTEGER(734)
+DEFINE_INTEGER(735)
+DEFINE_INTEGER(736)
+DEFINE_INTEGER(737)
+DEFINE_INTEGER(738)
+DEFINE_INTEGER(739)
+DEFINE_INTEGER(740)
+DEFINE_INTEGER(741)
+DEFINE_INTEGER(742)
+DEFINE_INTEGER(743)
+DEFINE_INTEGER(744)
+DEFINE_INTEGER(745)
+DEFINE_INTEGER(746)
+DEFINE_INTEGER(747)
+DEFINE_INTEGER(748)
+DEFINE_INTEGER(749)
+DEFINE_INTEGER(750)
+DEFINE_INTEGER(751)
+DEFINE_INTEGER(752)
+DEFINE_INTEGER(753)
+DEFINE_INTEGER(754)
+DEFINE_INTEGER(755)
+DEFINE_INTEGER(756)
+DEFINE_INTEGER(757)
+DEFINE_INTEGER(758)
+DEFINE_INTEGER(759)
+DEFINE_INTEGER(760)
+DEFINE_INTEGER(761)
+DEFINE_INTEGER(762)
+DEFINE_INTEGER(763)
+DEFINE_INTEGER(764)
+DEFINE_INTEGER(765)
+DEFINE_INTEGER(766)
+DEFINE_INTEGER(767)
+DEFINE_INTEGER(768)
+DEFINE_INTEGER(769)
+DEFINE_INTEGER(770)
+DEFINE_INTEGER(771)
+DEFINE_INTEGER(772)
+DEFINE_INTEGER(773)
+DEFINE_INTEGER(774)
+DEFINE_INTEGER(775)
+DEFINE_INTEGER(776)
+DEFINE_INTEGER(777)
+DEFINE_INTEGER(778)
+DEFINE_INTEGER(779)
+DEFINE_INTEGER(780)
+DEFINE_INTEGER(781)
+DEFINE_INTEGER(782)
+DEFINE_INTEGER(783)
+DEFINE_INTEGER(784)
+DEFINE_INTEGER(785)
+DEFINE_INTEGER(786)
+DEFINE_INTEGER(787)
+DEFINE_INTEGER(788)
+DEFINE_INTEGER(789)
+DEFINE_INTEGER(790)
+DEFINE_INTEGER(791)
+DEFINE_INTEGER(792)
+DEFINE_INTEGER(793)
+DEFINE_INTEGER(794)
+DEFINE_INTEGER(795)
+DEFINE_INTEGER(796)
+DEFINE_INTEGER(797)
+DEFINE_INTEGER(798)
+DEFINE_INTEGER(799)
+DEFINE_INTEGER(800)
+DEFINE_INTEGER(801)
+DEFINE_INTEGER(802)
+DEFINE_INTEGER(803)
+DEFINE_INTEGER(804)
+DEFINE_INTEGER(805)
+DEFINE_INTEGER(806)
+DEFINE_INTEGER(807)
+DEFINE_INTEGER(808)
+DEFINE_INTEGER(809)
+DEFINE_INTEGER(810)
+DEFINE_INTEGER(811)
+DEFINE_INTEGER(812)
+DEFINE_INTEGER(813)
+DEFINE_INTEGER(814)
+DEFINE_INTEGER(815)
+DEFINE_INTEGER(816)
+DEFINE_INTEGER(817)
diff --git a/tests/gpgscm/t-child.c b/tests/gpgscm/t-child.c
new file mode 100644
index 0000000..f4e3a04
--- /dev/null
+++ b/tests/gpgscm/t-child.c
@@ -0,0 +1,74 @@
+/* Sanity check for the process and IPC primitives.
+ *
+ * Copyright (C) 2016 g10 code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef _WIN32
+# include <fcntl.h>
+# include <io.h>
+#endif
+
+int
+main (int argc, char **argv)
+{
+ char buffer[4096];
+ memset (buffer, 'A', sizeof buffer);
+#if _WIN32
+ if (! setmode (fileno (stdin), O_BINARY))
+ return 23;
+ if (! setmode (fileno (stdout), O_BINARY))
+ return 23;
+#endif
+
+ if (argc == 1)
+ return 2;
+ else if (strcmp (argv[1], "return0") == 0)
+ return 0;
+ else if (strcmp (argv[1], "return1") == 0)
+ return 1;
+ else if (strcmp (argv[1], "return77") == 0)
+ return 77;
+ else if (strcmp (argv[1], "hello_stdout") == 0)
+ fprintf (stdout, "hello");
+ else if (strcmp (argv[1], "hello_stderr") == 0)
+ fprintf (stderr, "hello");
+ else if (strcmp (argv[1], "stdout4096") == 0)
+ fwrite (buffer, 1, sizeof buffer, stdout);
+ else if (strcmp (argv[1], "stdout8192") == 0)
+ {
+ fwrite (buffer, 1, sizeof buffer, stdout);
+ fwrite (buffer, 1, sizeof buffer, stdout);
+ }
+ else if (strcmp (argv[1], "cat") == 0)
+ while (! feof (stdin))
+ {
+ size_t bytes_read;
+ bytes_read = fread (buffer, 1, sizeof buffer, stdin);
+ fwrite (buffer, 1, bytes_read, stdout);
+ }
+ else
+ {
+ fprintf (stderr, "unknown command %s\n", argv[1]);
+ return 2;
+ }
+ return 0;
+}
diff --git a/tests/gpgscm/t-child.scm b/tests/gpgscm/t-child.scm
new file mode 100644
index 0000000..fd1dcc3
--- /dev/null
+++ b/tests/gpgscm/t-child.scm
@@ -0,0 +1,118 @@
+;; Tests for the low-level process and IPC primitives.
+;;
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(echo "Testing process and IPC primitives...")
+
+(define (qualify executable)
+ (string-append executable (getenv "EXEEXT")))
+
+(define child (qualify "t-child"))
+
+(assert (= 0 (call `(,(qualify "t-child") "return0"))))
+(assert (= 1 (call `(,(qualify "t-child") "return1"))))
+(assert (= 77 (call `(,(qualify "t-child") "return77"))))
+
+(let ((r (call-with-io `(,(qualify "t-child") "return0") "")))
+ (assert (= 0 (:retcode r)))
+ (assert (string=? "" (:stdout r)))
+ (assert (string=? "" (:stderr r))))
+
+(let ((r (call-with-io `(,(qualify "t-child") "return1") "")))
+ (assert (= 1 (:retcode r)))
+ (assert (string=? "" (:stdout r)))
+ (assert (string=? "" (:stderr r))))
+
+(let ((r (call-with-io `(,(qualify "t-child") "return77") "")))
+ (assert (= 77 (:retcode r)))
+ (assert (string=? "" (:stdout r)))
+ (assert (string=? "" (:stderr r))))
+
+(let ((r (call-with-io `(,(qualify "t-child") "hello_stdout") "")))
+ (assert (= 0 (:retcode r)))
+ (assert (string=? "hello" (:stdout r)))
+ (assert (string=? "" (:stderr r))))
+
+(let ((r (call-with-io `(,(qualify "t-child") "hello_stderr") "")))
+ (assert (= 0 (:retcode r)))
+ (assert (string=? "" (:stdout r)))
+ (assert (string=? "hello" (:stderr r))))
+
+(let ((r (call-with-io `(,(qualify "t-child") "stdout4096") "")))
+ (assert (= 0 (:retcode r)))
+ (assert (= 4096 (string-length (:stdout r))))
+ (assert (string=? "" (:stderr r))))
+
+(let ((r (call-with-io `(,(qualify "t-child") "stdout8192") "")))
+ (assert (= 0 (:retcode r)))
+ (assert (= 8192 (string-length (:stdout r))))
+ (assert (string=? "" (:stderr r))))
+
+(let ((r (call-with-io `(,(qualify "t-child") "cat") "hellohello")))
+ (assert (= 0 (:retcode r)))
+ (assert (string=? "hellohello" (:stdout r)))
+ (assert (string=? "" (:stderr r))))
+
+(define (spawn what)
+ (spawn-process-fd what CLOSED_FD STDOUT_FILENO STDERR_FILENO))
+
+(let ((pid0 (spawn `(,(qualify "t-child") "return0")))
+ (pid1 (spawn `(,(qualify "t-child") "return0"))))
+ (assert (equal? '(0 0)
+ (wait-processes '("child0" "child1") (list pid0 pid1) #t))))
+
+(let ((pid0 (spawn `(,(qualify "t-child") "return1")))
+ (pid1 (spawn `(,(qualify "t-child") "return0"))))
+ (assert (equal? '(1 0)
+ (wait-processes '("child0" "child1") (list pid0 pid1) #t))))
+
+(let ((pid0 (spawn `(,(qualify "t-child") "return0")))
+ (pid1 (spawn `(,(qualify "t-child") "return77")))
+ (pid2 (spawn `(,(qualify "t-child") "return1"))))
+ (assert (equal? '(0 77 1)
+ (wait-processes '("child0" "child1" "child2")
+ (list pid0 pid1 pid2) #t))))
+
+(let* ((p (pipe))
+ (pid0 (spawn-process-fd
+ `(,(qualify "t-child") "hello_stdout")
+ CLOSED_FD (:write-end p) STDERR_FILENO))
+ (_ (close (:write-end p)))
+ (pid1 (spawn-process-fd
+ `(,(qualify "t-child") "cat")
+ (:read-end p) STDOUT_FILENO STDERR_FILENO)))
+ (close (:read-end p))
+ (assert
+ (equal? '(0 0)
+ (wait-processes '("child0" "child1") (list pid0 pid1) #t))))
+(echo " world.")
+
+(tr:do
+ (tr:pipe-do
+ (pipe:spawn `(,child stdout4096))
+ (pipe:spawn `(,child cat)))
+ (tr:call-with-content (lambda (c)
+ (assert (= 4096 (string-length c))))))
+(tr:do
+ (tr:pipe-do
+ (pipe:spawn `(,child stdout8192))
+ (pipe:spawn `(,child cat)))
+ (tr:call-with-content (lambda (c)
+ (assert (= 8192 (string-length c))))))
+
+(echo "All good.")
diff --git a/tests/gpgscm/tests.scm b/tests/gpgscm/tests.scm
new file mode 100644
index 0000000..5141002
--- /dev/null
+++ b/tests/gpgscm/tests.scm
@@ -0,0 +1,886 @@
+;; Common definitions for writing tests.
+;;
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+;; Reporting.
+(define (echo . msg)
+ (for-each (lambda (x) (display x) (display " ")) msg)
+ (newline))
+
+(define (info . msg)
+ (apply echo msg)
+ (flush-stdio))
+
+(define (log . msg)
+ (if (> (*verbose*) 0)
+ (apply info msg)))
+
+(define (fail . msg)
+ (apply info msg)
+ (exit 1))
+
+(define (skip . msg)
+ (apply info msg)
+ (exit 77))
+
+(define (make-counter)
+ (let ((c 0))
+ (lambda ()
+ (let ((r c))
+ (set! c (+ 1 c))
+ r))))
+
+(define *progress-nesting* 0)
+
+(define (call-with-progress msg what)
+ (set! *progress-nesting* (+ 1 *progress-nesting*))
+ (if (= 1 *progress-nesting*)
+ (begin
+ (info msg)
+ (display " > ")
+ (flush-stdio)
+ (what (lambda (item)
+ (display item)
+ (display " ")
+ (flush-stdio)))
+ (info "< "))
+ (begin
+ (what (lambda (item) (display ".") (flush-stdio)))
+ (display " ")
+ (flush-stdio)))
+ (set! *progress-nesting* (- *progress-nesting* 1)))
+
+(define (for-each-p msg proc lst . lsts)
+ (apply for-each-p' `(,msg ,proc ,(lambda (x . xs) x) ,lst ,@lsts)))
+
+(define (for-each-p' msg proc fmt lst . lsts)
+ (call-with-progress
+ msg
+ (lambda (progress)
+ (apply for-each
+ `(,(lambda args
+ (progress (apply fmt args))
+ (apply proc args))
+ ,lst ,@lsts)))))
+
+;; Process management.
+(define CLOSED_FD -1)
+(define (call-with-fds what infd outfd errfd)
+ (wait-process (stringify what) (spawn-process-fd what infd outfd errfd) #t))
+(define (call what)
+ (call-with-fds what
+ CLOSED_FD
+ (if (< (*verbose*) 0) STDOUT_FILENO CLOSED_FD)
+ (if (< (*verbose*) 0) STDERR_FILENO CLOSED_FD)))
+
+;; Accessor functions for the results of 'spawn-process'.
+(define :stdin car)
+(define :stdout cadr)
+(define :stderr caddr)
+(define :pid cadddr)
+
+(define (call-with-io what in)
+ (let ((h (spawn-process what 0)))
+ (es-write (:stdin h) in)
+ (es-fclose (:stdin h))
+ (let* ((out (es-read-all (:stdout h)))
+ (err (es-read-all (:stderr h)))
+ (result (wait-process (car what) (:pid h) #t)))
+ (es-fclose (:stdout h))
+ (es-fclose (:stderr h))
+ (if (> (*verbose*) 2)
+ (info "Child" (:pid h) "returned:"
+ `((command ,(stringify what))
+ (status ,result)
+ (stdout ,out)
+ (stderr ,err))))
+ (list result out err))))
+
+;; Accessor function for the results of 'call-with-io'. ':stdout' and
+;; ':stderr' can also be used.
+(define :retcode car)
+
+(define (call-check what)
+ (let ((result (call-with-io what "")))
+ (if (= 0 (:retcode result))
+ (:stdout result)
+ (throw (string-append (stringify what) " failed")
+ (:stderr result)))))
+
+(define (call-popen command input-string)
+ (let ((result (call-with-io command input-string)))
+ (if (= 0 (:retcode result))
+ (:stdout result)
+ (throw (:stderr result)))))
+
+;;
+;; estream helpers.
+;;
+
+(define (es-read-all stream)
+ (let loop
+ ((acc ""))
+ (if (es-feof stream)
+ acc
+ (loop (string-append acc (es-read stream 4096))))))
+
+;;
+;; File management.
+;;
+(define (file-exists? name)
+ (call-with-input-file name (lambda (port) #t)))
+
+(define (file=? a b)
+ (file-equal a b #t))
+
+(define (text-file=? a b)
+ (file-equal a b #f))
+
+(define (file-copy from to)
+ (catch '() (unlink to))
+ (letfd ((source (open from (logior O_RDONLY O_BINARY)))
+ (sink (open to (logior O_WRONLY O_CREAT O_BINARY) #o600)))
+ (splice source sink)))
+
+(define (text-file-copy from to)
+ (catch '() (unlink to))
+ (letfd ((source (open from O_RDONLY))
+ (sink (open to (logior O_WRONLY O_CREAT) #o600)))
+ (splice source sink)))
+
+(define (path-join . components)
+ (let loop ((acc #f) (rest (filter (lambda (s)
+ (not (string=? "" s))) components)))
+ (if (null? rest)
+ acc
+ (loop (if (string? acc)
+ (string-append acc "/" (car rest))
+ (car rest))
+ (cdr rest)))))
+(assert (string=? (path-join "foo" "bar" "baz") "foo/bar/baz"))
+(assert (string=? (path-join "" "bar" "baz") "bar/baz"))
+
+;; Is PATH an absolute path?
+(define (absolute-path? path)
+ (or (char=? #\/ (string-ref path 0))
+ (and *win32* (char=? #\\ (string-ref path 0)))
+ (and *win32*
+ (char-alphabetic? (string-ref path 0))
+ (char=? #\: (string-ref path 1))
+ (or (char=? #\/ (string-ref path 2))
+ (char=? #\\ (string-ref path 2))))))
+
+;; Make PATH absolute.
+(define (canonical-path path)
+ (if (absolute-path? path) path (path-join (getcwd) path)))
+
+(define (in-srcdir . names)
+ (canonical-path (apply path-join (cons (getenv "abs_top_srcdir") names))))
+
+;; Split a list of paths.
+(define (pathsep-split s)
+ (string-split s *pathsep*))
+
+;; Join a list of paths.
+(define (pathsep-join paths)
+ (foldr (lambda (a b) (string-append a (string *pathsep*) b))
+ (car paths)
+ (cdr paths)))
+
+;; Try to find NAME in PATHS. Returns the full path name on success,
+;; or raises an error.
+(define (path-expand name paths)
+ (let loop ((path paths))
+ (if (null? path)
+ (throw "Could not find" name "in" paths)
+ (let* ((qualified-name (path-join (car path) name))
+ (file-exists (call-with-input-file qualified-name
+ (lambda (x) #t))))
+ (if file-exists
+ qualified-name
+ (loop (cdr path)))))))
+
+;; Expand NAME using the gpgscm load path. Use like this:
+;; (load (with-path "library.scm"))
+(define (with-path name)
+ (catch name
+ (path-expand name (pathsep-split (getenv "GPGSCM_PATH")))))
+
+(define (basename path)
+ (let ((i (string-index path #\/)))
+ (if (equal? i #f)
+ path
+ (basename (substring path (+ 1 i) (string-length path))))))
+
+(define (basename-suffix path suffix)
+ (basename
+ (if (string-suffix? path suffix)
+ (substring path 0 (- (string-length path) (string-length suffix)))
+ path)))
+
+(define (dirname path)
+ (let ((i (string-rindex path #\/)))
+ (if i (substring path 0 i) ".")))
+(assert (string=? "foo/bar" (dirname "foo/bar/baz")))
+
+;; Helper for (pipe).
+(define :read-end car)
+(define :write-end cadr)
+
+;; let-like macro that manages file descriptors.
+;;
+;; (letfd <bindings> <body>)
+;;
+;; Bind all variables given in <bindings> and initialize each of them
+;; to the given initial value, and close them after evaluating <body>.
+(define-macro (letfd bindings . body)
+ (let bind ((bindings' bindings))
+ (if (null? bindings')
+ `(begin ,@body)
+ (let* ((binding (car bindings'))
+ (name (car binding))
+ (initializer (cadr binding)))
+ `(let ((,name ,initializer))
+ (finally (close ,name)
+ ,(bind (cdr bindings'))))))))
+
+(define-macro (with-working-directory new-directory . expressions)
+ (let ((new-dir (gensym))
+ (old-dir (gensym)))
+ `(let* ((,new-dir ,new-directory)
+ (,old-dir (getcwd)))
+ (dynamic-wind
+ (lambda () (if ,new-dir (chdir ,new-dir)))
+ (lambda () ,@expressions)
+ (lambda () (chdir ,old-dir))))))
+
+;; Make a temporary directory. If arguments are given, they are
+;; joined using path-join, and must end in a component ending in
+;; "XXXXXX". If no arguments are given, a suitable location and
+;; generic name is used. Returns an absolute path.
+(define (mkdtemp . components)
+ (canonical-path (_mkdtemp (if (null? components)
+ (path-join
+ (get-temp-path)
+ (string-append "gpgscm-" (get-isotime) "-"
+ (basename-suffix *scriptname* ".scm")
+ "-XXXXXX"))
+ (apply path-join components)))))
+
+;; Make a temporary directory and remove it at interpreter shutdown.
+;; Note that there are macros that limit the lifetime of temporary
+;; directories and files to a lexical scope. Use those if possible.
+;; Otherwise this works like mkdtemp.
+(define (mkdtemp-autoremove . components)
+ (let ((dir (apply mkdtemp components)))
+ (atexit (lambda () (unlink-recursively dir)))
+ dir))
+
+(define-macro (with-temporary-working-directory . expressions)
+ (let ((tmp-sym (gensym)))
+ `(let* ((,tmp-sym (mkdtemp)))
+ (finally (unlink-recursively ,tmp-sym)
+ (with-working-directory ,tmp-sym
+ ,@expressions)))))
+
+(define (make-temporary-file . args)
+ (canonical-path (path-join
+ (mkdtemp)
+ (if (null? args) "a" (car args)))))
+
+(define (remove-temporary-file filename)
+ (catch '()
+ (unlink filename))
+ (let ((dirname (substring filename 0 (string-rindex filename #\/))))
+ (catch (echo "removing temporary directory" dirname "failed")
+ (rmdir dirname))))
+
+;; let-like macro that manages temporary files.
+;;
+;; (lettmp <bindings> <body>)
+;;
+;; Bind all variables given in <bindings>, initialize each of them to
+;; a string representing an unique path in the filesystem, and delete
+;; them after evaluating <body>.
+(define-macro (lettmp bindings . body)
+ (let bind ((bindings' bindings))
+ (if (null? bindings')
+ `(begin ,@body)
+ (let ((name (car bindings'))
+ (rest (cdr bindings')))
+ `(let ((,name (make-temporary-file ,(symbol->string name))))
+ (finally (remove-temporary-file ,name)
+ ,(bind rest)))))))
+
+(define (check-execution source transformer)
+ (lettmp (sink)
+ (transformer source sink)))
+
+(define (check-identity source transformer)
+ (lettmp (sink)
+ (transformer source sink)
+ (if (not (file=? source sink))
+ (fail "mismatch"))))
+
+;;
+;; Monadic pipe support.
+;;
+
+(define pipeM
+ (package
+ (define (new procs source sink producer)
+ (package
+ (define (dump)
+ (write (list procs source sink producer))
+ (newline))
+ (define (add-proc command pid)
+ (new (cons (list command pid) procs) source sink producer))
+ (define (commands)
+ (map car procs))
+ (define (pids)
+ (map cadr procs))
+ (define (set-source source')
+ (new procs source' sink producer))
+ (define (set-sink sink')
+ (new procs source sink' producer))
+ (define (set-producer producer')
+ (if producer
+ (throw "producer already set"))
+ (new procs source sink producer'))))))
+
+
+(define (pipe:do . commands)
+ (let loop ((M (pipeM::new '() CLOSED_FD CLOSED_FD #f)) (cmds commands))
+ (if (null? cmds)
+ (begin
+ (if M::producer (M::producer))
+ (if (not (null? M::procs))
+ (let* ((retcodes (wait-processes (map stringify (M::commands))
+ (M::pids) #t))
+ (results (map (lambda (p r) (append p (list r)))
+ M::procs retcodes))
+ (failed (filter (lambda (x) (not (= 0 (caddr x))))
+ results)))
+ (if (not (null? failed))
+ (throw failed))))) ; xxx nicer reporting
+ (if (and (= 2 (length cmds)) (number? (cadr cmds)))
+ ;; hack: if it's an fd, use it as sink
+ (let ((M' ((car cmds) (M::set-sink (cadr cmds)))))
+ (if (> M::source 2) (close M::source))
+ (if (> (cadr cmds) 2) (close (cadr cmds)))
+ (loop M' '()))
+ (let ((M' ((car cmds) M)))
+ (if (> M::source 2) (close M::source))
+ (loop M' (cdr cmds)))))))
+
+(define (pipe:open pathname flags)
+ (lambda (M)
+ (M::set-source (open pathname flags))))
+
+(define (pipe:defer producer)
+ (lambda (M)
+ (let* ((p (outbound-pipe))
+ (M' (M::set-source (:read-end p))))
+ (M'::set-producer (lambda ()
+ (producer (:write-end p))
+ (close (:write-end p)))))))
+(define (pipe:echo data)
+ (pipe:defer (lambda (sink) (display data (fdopen sink "wb")))))
+
+(define (pipe:spawn command)
+ (lambda (M)
+ (define (do-spawn M new-source)
+ (let ((pid (spawn-process-fd command M::source M::sink
+ (if (> (*verbose*) 0)
+ STDERR_FILENO CLOSED_FD)))
+ (M' (M::set-source new-source)))
+ (M'::add-proc command pid)))
+ (if (= CLOSED_FD M::sink)
+ (let* ((p (pipe))
+ (M' (do-spawn (M::set-sink (:write-end p)) (:read-end p))))
+ (close (:write-end p))
+ (M'::set-sink CLOSED_FD))
+ (do-spawn M CLOSED_FD))))
+
+(define (pipe:splice sink)
+ (lambda (M)
+ (splice M::source sink)
+ (M::set-source CLOSED_FD)))
+
+(define (pipe:write-to pathname flags mode)
+ (open pathname flags mode))
+
+;;
+;; Monadic transformer support.
+;;
+
+(define (tr:do . commands)
+ (let loop ((tmpfiles '()) (source #f) (cmds commands))
+ (if (null? cmds)
+ (for-each remove-temporary-file tmpfiles)
+ (let* ((v ((car cmds) tmpfiles source))
+ (tmpfiles' (car v))
+ (sink (cadr v))
+ (error (caddr v)))
+ (if error
+ (begin
+ (for-each remove-temporary-file tmpfiles')
+ (apply throw error)))
+ (loop tmpfiles' sink (cdr cmds))))))
+
+(define (tr:open pathname)
+ (lambda (tmpfiles source)
+ (list tmpfiles pathname #f)))
+
+(define (tr:spawn input command)
+ (lambda (tmpfiles source)
+ (if (and (member '**in** command) (not source))
+ (fail (string-append (stringify cmd) " needs an input")))
+ (let* ((t (make-temporary-file))
+ (cmd (map (lambda (x)
+ (cond
+ ((equal? '**in** x) source)
+ ((equal? '**out** x) t)
+ (else x))) command)))
+ (catch (list (cons t tmpfiles) t *error*)
+ (call-popen cmd input)
+ (if (and (member '**out** command) (not (file-exists? t)))
+ (fail (string-append (stringify cmd)
+ " did not produce '" t "'.")))
+ (list (cons t tmpfiles) t #f)))))
+
+(define (tr:write-to pathname)
+ (lambda (tmpfiles source)
+ (rename source pathname)
+ (list tmpfiles pathname #f)))
+
+(define (tr:pipe-do . commands)
+ (lambda (tmpfiles source)
+ (let ((t (make-temporary-file)))
+ (apply pipe:do
+ `(,@(if source `(,(pipe:open source (logior O_RDONLY O_BINARY))) '())
+ ,@commands
+ ,(pipe:write-to t (logior O_WRONLY O_BINARY O_CREAT) #o600)))
+ (list (cons t tmpfiles) t #f))))
+
+(define (tr:assert-identity reference)
+ (lambda (tmpfiles source)
+ (if (not (file=? source reference))
+ (fail "mismatch"))
+ (list tmpfiles source #f)))
+
+(define (tr:assert-weak-identity reference)
+ (lambda (tmpfiles source)
+ (if (not (text-file=? source reference))
+ (fail "mismatch"))
+ (list tmpfiles source #f)))
+
+(define (tr:call-with-content function . args)
+ (lambda (tmpfiles source)
+ (catch (list tmpfiles source *error*)
+ (apply function `(,(call-with-input-file source read-all) ,@args)))
+ (list tmpfiles source #f)))
+
+;;
+;; Developing and debugging tests.
+;;
+
+;; Spawn an os shell.
+(define (interactive-shell)
+ (call-with-fds `(,(getenv "SHELL") -i) 0 1 2))
+
+;;
+;; The main test framework.
+;;
+
+(define semaphore
+ (package
+ (define (new n)
+ (package
+ (define (acquire!?)
+ (if (> n 0)
+ (begin
+ (set! n (- n 1))
+ #t)
+ #f))
+ (define (release!)
+ (set! n (+ n 1)))))))
+
+;; A pool of tests.
+(define test-pool
+ (package
+ (define (new n)
+ (package
+ ;; A semaphore to restrict the number of spawned processes.
+ (define sem (semaphore::new n))
+
+ ;; A list of enqueued, but not yet run tests.
+ (define enqueued '())
+
+ ;; A list of running or finished processes.
+ (define procs '())
+
+ (define (add test)
+ (if (test::started?)
+ (set! procs (cons test procs))
+ (if (sem::acquire!?)
+ (add (test::run-async))
+ (set! enqueued (cons test enqueued))))
+ (current-environment))
+
+ ;; Pop the last of the enqueued tests off the fifo queue.
+ (define (pop-test!)
+ (let ((i (length enqueued)))
+ (assert (> i 0))
+ (cond
+ ((= i 1)
+ (let ((test (car enqueued)))
+ (set! enqueued '())
+ test))
+ (else
+ (let* ((tail (list-tail enqueued (- i 2)))
+ (test (cadr tail)))
+ (set-cdr! tail '())
+ (assert (= (length enqueued) (- i 1)))
+ test)))))
+
+ (define (pid->test pid)
+ (let ((t (filter (lambda (x) (= pid x::pid)) procs)))
+ (if (null? t) #f (car t))))
+ (define (wait)
+ (if (null? enqueued)
+ ;; If no tests are enqueued, we can just block until all
+ ;; of them finished.
+ (wait' #t)
+ ;; Otherwise, we must not block, but give some tests the
+ ;; chance to finish so that we can start new ones.
+ (begin
+ (wait' #f)
+ (usleep (/ 1000000 10))
+ (wait))))
+ (define (wait' hang)
+ (let ((unfinished (filter (lambda (t) (not t::retcode)) procs)))
+ (if (null? unfinished)
+ (current-environment)
+ (let ((names (map (lambda (t) t::name) unfinished))
+ (pids (map (lambda (t) t::pid) unfinished))
+ (any #f))
+ (for-each
+ (lambda (test retcode)
+ (unless (< retcode 0)
+ (test::set-end-time!)
+ (test:::set! 'retcode retcode)
+ (test::report)
+ (sem::release!)
+ (set! any #t)))
+ (map pid->test pids)
+ (wait-processes (map stringify names) pids hang))
+
+ ;; If some processes finished, try to start new ones.
+ (let loop ()
+ (cond
+ ((not any) #f)
+ ((pair? enqueued)
+ (if (sem::acquire!?)
+ (let ((test (pop-test!)))
+ (add (test::run-async))
+ (loop)))))))))
+ (current-environment))
+ (define (filter-tests status)
+ (filter (lambda (p) (eq? status (p::status))) procs))
+ (define (report)
+ (define (print-tests tests message)
+ (unless (null? tests)
+ (apply echo (cons message
+ (map (lambda (t) t::name) tests)))))
+
+ (let ((failed (filter-tests 'FAIL))
+ (xfailed (filter-tests 'XFAIL))
+ (xpassed (filter-tests 'XPASS))
+ (skipped (filter-tests 'SKIP)))
+ (echo "===================")
+ (echo (length procs) "tests run,"
+ (length (filter-tests 'PASS)) "succeeded,"
+ (length failed) "failed,"
+ (length xfailed) "failed expectedly,"
+ (length xpassed) "succeeded unexpectedly,"
+ (length skipped) "skipped.")
+ (print-tests failed "Failed tests:")
+ (print-tests xfailed "Expectedly failed tests:")
+ (print-tests xpassed "Unexpectedly passed tests:")
+ (print-tests skipped "Skipped tests:")
+ (echo "===================")
+ (+ (length failed) (length xpassed))))
+
+ (define (xml)
+ (xx::document
+ (xx::tag 'testsuites
+ `((xmlns:xsi "http://www.w3.org/2001/XMLSchema-instance")
+ ("xsi:noNamespaceSchemaLocation"
+ "https://windyroad.com.au/dl/Open%20Source/JUnit.xsd"))
+ (map (lambda (t) (t::xml)) procs))))))))
+
+(define (verbosity n)
+ (if (= 0 n) '() (cons '--verbose (verbosity (- n 1)))))
+
+(define (locate-test path)
+ (if (absolute-path? path) path (in-srcdir path)))
+
+;; A single test.
+(define test
+ (begin
+
+ ;; Private definitions.
+
+ (define (isotime->junit t)
+ "[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}"
+ "20170418T145809"
+ (string-append (substring t 0 4)
+ "-"
+ (substring t 4 6)
+ "-"
+ (substring t 6 11)
+ ":"
+ (substring t 11 13)
+ ":"
+ (substring t 13 15)))
+
+ ;; If a tests name ends with a bang (!), it is expected to fail.
+ (define (expect-failure? name)
+ (string-suffix? name "!"))
+ ;; Strips the bang (if any).
+ (define (test-name name)
+ (if (expect-failure? name)
+ (substring name 0 (- (string-length name) 1))
+ name))
+
+ (package
+ (define (scm setup name path . args)
+ ;; Start the process.
+ (define (spawn-scm args' in out err)
+ (spawn-process-fd `(,*argv0* ,@(verbosity (*verbose*))
+ ,(locate-test (test-name path))
+ ,@(if setup (force setup) '())
+ ,@args' ,@args) in out err))
+ (new name #f spawn-scm #f #f CLOSED_FD (expect-failure? name)))
+
+ (define (binary setup name path . args)
+ ;; Start the process.
+ (define (spawn-binary args' in out err)
+ (spawn-process-fd `(,(test-name path)
+ ,@(if setup (force setup) '()) ,@args' ,@args)
+ in out err))
+ (new name #f spawn-binary #f #f CLOSED_FD (expect-failure? name)))
+
+ (define (new name directory spawn pid retcode logfd expect-failure)
+ (package
+
+ ;; XXX: OO glue.
+ (define self (current-environment))
+ (define (:set! key value)
+ (eval `(set! ,key ,value) (current-environment))
+ (current-environment))
+
+ ;; The log is written here.
+ (define log-file-name #f)
+
+ ;; Record time stamps.
+ (define timestamp #f)
+ (define start-time 0)
+ (define end-time 0)
+
+ (define (set-start-time!)
+ (set! timestamp (isotime->junit (get-isotime)))
+ (set! start-time (get-time)))
+ (define (set-end-time!)
+ (set! end-time (get-time)))
+
+ ;; Has the test been started yet?
+ (define (started?)
+ (number? pid))
+
+ (define (open-log-file)
+ (unless log-file-name
+ (set! log-file-name (string-append (basename name) ".log")))
+ (catch '() (unlink log-file-name))
+ (open log-file-name (logior O_RDWR O_BINARY O_CREAT) #o600))
+
+ (define (run-sync . args)
+ (set-start-time!)
+ (letfd ((log (open-log-file)))
+ (with-working-directory directory
+ (let* ((p (inbound-pipe))
+ (pid' (spawn args 0 (:write-end p) (:write-end p))))
+ (close (:write-end p))
+ (splice (:read-end p) STDERR_FILENO log)
+ (close (:read-end p))
+ (set! pid pid')
+ (set! retcode (wait-process name pid' #t)))))
+ (report)
+ (current-environment))
+ (define (run-sync-quiet . args)
+ (set-start-time!)
+ (with-working-directory directory
+ (set! pid (spawn args CLOSED_FD CLOSED_FD CLOSED_FD)))
+ (set! retcode (wait-process name pid #t))
+ (set-end-time!)
+ (current-environment))
+ (define (run-async . args)
+ (set-start-time!)
+ (let ((log (open-log-file)))
+ (with-working-directory directory
+ (set! pid (spawn args CLOSED_FD log log)))
+ (set! logfd log))
+ (current-environment))
+ (define (status)
+ (let* ((t' (assoc retcode '((0 PASS) (77 SKIP) (99 ERROR))))
+ (t (if (not t') 'FAIL (cadr t'))))
+ (if expect-failure
+ (case t ((PASS) 'XPASS) ((FAIL) 'XFAIL) (else t))
+ t)))
+ (define (status-string)
+ (cadr (assoc (status) '((PASS "PASS")
+ (SKIP "SKIP")
+ (ERROR "ERROR")
+ (FAIL "FAIL")
+ (XPASS "XPASS")
+ (XFAIL "XFAIL")))))
+ (define (report)
+ (unless (= logfd CLOSED_FD)
+ (seek logfd 0 SEEK_SET)
+ (splice logfd STDERR_FILENO)
+ (close logfd))
+ (echo (string-append (status-string) ":") name))
+
+ (define (xml)
+ (xx::tag
+ 'testsuite
+ `((name ,name)
+ (time ,(- end-time start-time))
+ (package ,(dirname name))
+ (id 0)
+ (timestamp ,timestamp)
+ (hostname "unknown")
+ (tests 1)
+ (failures ,(if (eq? FAIL (status)) 1 0))
+ (errors ,(if (eq? ERROR (status)) 1 0)))
+ (list
+ (xx::tag 'properties)
+ (xx::tag 'testcase
+ `((name ,(basename name))
+ (classname ,(string-translate (dirname name) "/" "."))
+ (time ,(- end-time start-time)))
+ `(,@(case (status)
+ ((PASS XFAIL) '())
+ ((SKIP) (list (xx::tag 'skipped)))
+ ((ERROR) (list
+ (xx::tag 'error '((message "Unknown error.")))))
+ (else
+ (list (xx::tag 'failure '((message "Unknown error."))))))))
+ (xx::tag 'system-out '()
+ (list (xx::textnode (read-all (open-input-file log-file-name)))))
+ (xx::tag 'system-err '() (list (xx::textnode "")))))))))))
+
+;; Run the setup target to create an environment, then run all given
+;; tests in parallel.
+(define (run-tests-parallel tests n)
+ (let loop ((pool (test-pool::new n)) (tests' tests))
+ (if (null? tests')
+ (let ((results (pool::wait)))
+ ((results::xml) (open-output-file "report.xml"))
+ (exit (results::report)))
+ (let ((wd (mkdtemp-autoremove))
+ (test (car tests')))
+ (test:::set! 'directory wd)
+ (loop (pool::add test)
+ (cdr tests'))))))
+
+;; Run the setup target to create an environment, then run all given
+;; tests in sequence.
+(define (run-tests-sequential tests)
+ (let loop ((pool (test-pool::new 1)) (tests' tests))
+ (if (null? tests')
+ (let ((results (pool::wait)))
+ ((results::xml) (open-output-file "report.xml"))
+ (exit (results::report)))
+ (let ((wd (mkdtemp-autoremove))
+ (test (car tests')))
+ (test:::set! 'directory wd)
+ (loop (pool::add (test::run-sync))
+ (cdr tests'))))))
+
+;; Run tests either in sequence or in parallel, depending on the
+;; number of tests and the command line flags.
+(define (run-tests tests)
+ (let ((parallel (flag "--parallel" *args*))
+ (default-parallel-jobs 32))
+ (if (and parallel (> (length tests) 1))
+ (run-tests-parallel tests (if (and (pair? parallel)
+ (string->number (car parallel)))
+ (string->number (car parallel))
+ default-parallel-jobs))
+ (run-tests-sequential tests))))
+
+;; Load all tests from the given path.
+(define (load-tests . path)
+ (load (apply in-srcdir `(,@path "all-tests.scm")))
+ all-tests)
+
+;; Helper to create environment caches from test functions. SETUP
+;; must be a test implementing the producer side cache protocol.
+;; Returns a promise containing the arguments that must be passed to a
+;; test implementing the consumer side of the cache protocol.
+(define (make-environment-cache setup)
+ (delay (with-temporary-working-directory
+ (let ((tarball (make-temporary-file "environment-cache")))
+ (atexit (lambda () (remove-temporary-file tarball)))
+ (setup::run-sync '--create-tarball tarball)
+ (if (not (equal? 'PASS (setup::status)))
+ (fail "Setup failed."))
+ `(--unpack-tarball ,tarball)))))
+
+;; Command line flag handling. Returns the elements following KEY in
+;; ARGUMENTS up to the next argument, or #f if KEY is not in
+;; ARGUMENTS. If 'KEY=XYZ' is encountered, then the singleton list
+;; containing 'XYZ' is returned.
+(define (flag key arguments)
+ (cond
+ ((null? arguments)
+ #f)
+ ((string=? key (car arguments))
+ (let loop ((acc '())
+ (args (cdr arguments)))
+ (if (or (null? args) (string-prefix? (car args) "--"))
+ (reverse acc)
+ (loop (cons (car args) acc) (cdr args)))))
+ ((string-prefix? (car arguments) (string-append key "="))
+ (list (substring (car arguments)
+ (+ (string-length key) 1)
+ (string-length (car arguments)))))
+ ((string=? "--" (car arguments))
+ #f)
+ (else
+ (flag key (cdr arguments)))))
+(assert (equal? (flag "--xxx" '("--yyy")) #f))
+(assert (equal? (flag "--xxx" '("--xxx")) '()))
+(assert (equal? (flag "--xxx" '("--xxx" "yyy")) '("yyy")))
+(assert (equal? (flag "--xxx" '("--xxx=foo" "yyy")) '("foo")))
+(assert (equal? (flag "--xxx" '("--xxx" "yyy" "zzz")) '("yyy" "zzz")))
+(assert (equal? (flag "--xxx" '("--xxx" "yyy" "zzz" "--")) '("yyy" "zzz")))
+(assert (equal? (flag "--xxx" '("--xxx" "yyy" "--" "zzz")) '("yyy")))
+(assert (equal? (flag "--" '("--" "xxx" "yyy" "--" "zzz")) '("xxx" "yyy")))
diff --git a/tests/gpgscm/time.scm b/tests/gpgscm/time.scm
new file mode 100644
index 0000000..a9b06d0
--- /dev/null
+++ b/tests/gpgscm/time.scm
@@ -0,0 +1,42 @@
+;; Simple time manipulation library.
+;;
+;; Copyright (C) 2017 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+;; This library mimics what GnuPG thinks about expiration times.
+;; Granularity is one second. Its focus is not on correctness.
+
+;; Conversion functions.
+(define (minutes->seconds minutes)
+ (* minutes 60))
+(define (hours->seconds hours)
+ (* hours 60 60))
+(define (days->seconds days)
+ (* days 24 60 60))
+(define (weeks->seconds weeks)
+ (days->seconds (* weeks 7)))
+(define (months->seconds months)
+ (days->seconds (* months 30)))
+(define (years->seconds years)
+ (days->seconds (* years 365)))
+
+(define (time-matches? a b slack)
+ (< (abs (- a b)) slack))
+(assert (time-matches? (hours->seconds 1) (hours->seconds 2) (hours->seconds 2)))
+(assert (time-matches? (hours->seconds 2) (hours->seconds 1) (hours->seconds 2)))
+(assert (not (time-matches? (hours->seconds 4) (hours->seconds 1) (hours->seconds 2))))
+(assert (not (time-matches? (hours->seconds 1) (hours->seconds 4) (hours->seconds 2))))
diff --git a/tests/gpgscm/xml.scm b/tests/gpgscm/xml.scm
new file mode 100644
index 0000000..771ec36
--- /dev/null
+++ b/tests/gpgscm/xml.scm
@@ -0,0 +1,142 @@
+;; A tiny XML library.
+;;
+;; Copyright (C) 2017 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(define xx
+ (begin
+
+ ;; Private declarations.
+ (define quote-text
+ '((#\< "&lt;")
+ (#\> "&gt;")
+ (#\& "&amp;")))
+
+ (define quote-attribute-'
+ '((#\< "&lt;")
+ (#\> "&gt;")
+ (#\& "&amp;")
+ (#\' "&apos;")))
+
+ (define quote-attribute-''
+ '((#\< "&lt;")
+ (#\> "&gt;")
+ (#\& "&amp;")
+ (#\" "&quot;")))
+
+ (define (escape-string quotation string sink)
+ ;; This implementation is a bit awkward because iteration is so
+ ;; slow in TinySCHEME. We rely on string-index to skip to the
+ ;; next character we need to escape. We also avoid allocations
+ ;; wherever possible.
+
+ ;; Given a list of integers or #f, return the sublist that
+ ;; starts with the lowest integer.
+ (define (min* x)
+ (let loop ((lowest x) (rest x))
+ (if (null? rest)
+ lowest
+ (loop (if (or (null? lowest) (not (car lowest))
+ (and (car rest) (> (car lowest) (car rest)))) rest lowest)
+ (cdr rest)))))
+
+ (let ((i 0) (start 0) (len (string-length string))
+ (indices (map (lambda (x) (string-index string (car x))) quotation))
+ (next #f) (c #f))
+
+ ;; Set 'i' to the index of the next character that needs
+ ;; escaping, 'c' to the character that needs to be escaped,
+ ;; and update 'indices'.
+ (define (skip!)
+ (set! next (min* indices))
+ (set! i (if (null? next) #f (car next)))
+ (if i
+ (begin
+ (set! c (string-ref string i))
+ (set-car! next (string-index string c (+ 1 i))))
+ (set! i (string-length string))))
+
+ (let loop ()
+ (skip!)
+ (if (< i len)
+ (begin
+ (display (substring string start i) sink)
+ (display (cadr (assv c quotation)) sink)
+ (set! i (+ 1 i))
+ (set! start i)
+ (loop))
+ (display (substring string start len) sink)))))
+
+ (let ((escape-string-s (lambda (quotation string)
+ (let ((sink (open-output-string)))
+ (escape-string quotation string sink)
+ (get-output-string sink)))))
+ (assert (equal? (escape-string-s quote-text "foo") "foo"))
+ (assert (equal? (escape-string-s quote-text "foo&") "foo&amp;"))
+ (assert (equal? (escape-string-s quote-text "&foo") "&amp;foo"))
+ (assert (equal? (escape-string-s quote-text "foo&bar") "foo&amp;bar"))
+ (assert (equal? (escape-string-s quote-text "foo<bar") "foo&lt;bar"))
+ (assert (equal? (escape-string-s quote-text "foo>bar") "foo&gt;bar")))
+
+ (define (escape quotation datum sink)
+ (cond
+ ((string? datum) (escape-string quotation datum sink))
+ ((symbol? datum) (escape-string quotation (symbol->string datum) sink))
+ ((number? datum) (display (number->string datum) sink))
+ (else
+ (throw "Do not know how to encode" datum))))
+
+ (define (name->string name)
+ (cond
+ ((symbol? name) (symbol->string name))
+ (else name)))
+
+ (package
+
+ (define (textnode string)
+ (lambda (sink)
+ (escape quote-text string sink)))
+
+ (define (tag name . rest)
+ (let ((attributes (if (null? rest) '() (car rest)))
+ (children (if (> (length rest) 1) (cadr rest) '())))
+ (lambda (sink)
+ (display "<" sink)
+ (display (name->string name) sink)
+ (unless (null? attributes)
+ (display " " sink)
+ (for-each (lambda (a)
+ (display (car a) sink)
+ (display "=\"" sink)
+ (escape quote-attribute-'' (cadr a) sink)
+ (display "\" " sink)) attributes))
+ (if (null? children)
+ (display "/>\n" sink)
+ (begin
+ (display ">\n" sink)
+ (for-each (lambda (c) (c sink)) children)
+ (display "</" sink)
+ (display (name->string name) sink)
+ (display ">\n" sink))))))
+
+ (define (document root . rest)
+ (let ((attributes (if (null? rest) '() (car rest))))
+ (lambda (sink)
+ ;; xxx ignores attributes
+ (display "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" sink)
+ (root sink)
+ (newline sink)))))))
diff --git a/tests/gpgsm/32100C27173EF6E9C4E9A25D3D69F86D37A4F939 b/tests/gpgsm/32100C27173EF6E9C4E9A25D3D69F86D37A4F939
new file mode 100644
index 0000000..7aa9bfd
--- /dev/null
+++ b/tests/gpgsm/32100C27173EF6E9C4E9A25D3D69F86D37A4F939
@@ -0,0 +1,10 @@
+(private-key
+ (oid.1.2.840.113549.1.1.1
+ (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)
+ (e #010001#)
+ (d #046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B117D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BDC543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781#)
+ (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)
+ (q #00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f935a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361#)
+ (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891eebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)
+ )
+)
diff --git a/tests/gpgsm/Makefile.am b/tests/gpgsm/Makefile.am
new file mode 100644
index 0000000..e784a31
--- /dev/null
+++ b/tests/gpgsm/Makefile.am
@@ -0,0 +1,75 @@
+# Makefile.am - For tests/gpgme
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+# Process this file with automake to create Makefile.in
+
+
+# Programs required before we can run these tests.
+required_pgms = ../../g10/gpg$(EXEEXT) ../../agent/gpg-agent$(EXEEXT) \
+ ../../tools/gpg-connect-agent$(EXEEXT) \
+ ../gpgscm/gpgscm$(EXEEXT)
+
+AM_CPPFLAGS = -I$(top_srcdir)/common
+include $(top_srcdir)/am/cmacros.am
+
+AM_CFLAGS =
+
+TESTS_ENVIRONMENT = LC_ALL=C \
+ EXEEXT=$(EXEEXT) \
+ PATH="../gpgscm:$(PATH)" \
+ abs_top_srcdir="$(abs_top_srcdir)" \
+ objdir="$(abs_top_builddir)" \
+ GPGSCM_PATH="$(abs_top_srcdir)/tests/gpgscm"
+
+XTESTS = \
+ import.scm \
+ encrypt.scm \
+ verify.scm \
+ decrypt.scm \
+ sign.scm \
+ export.scm
+
+# XXX: Currently, one cannot override automake's 'check' target. As a
+# workaround, we avoid defining 'TESTS', thus automake will not emit
+# the 'check' target. For extra robustness, we merely define a
+# dependency on 'xcheck', so this hack should also work even if
+# automake would emit the 'check' target, as adding dependencies to
+# targets is okay.
+check: xcheck
+
+.PHONY: xcheck
+xcheck:
+ $(TESTS_ENVIRONMENT) $(abs_top_builddir)/tests/gpgscm/gpgscm \
+ $(abs_srcdir)/run-tests.scm $(TESTFLAGS) $(TESTS)
+
+KEYS = 32100C27173EF6E9C4E9A25D3D69F86D37A4F939
+CERTS = cert_g10code_test1.der \
+ cert_dfn_pca01.der \
+ cert_dfn_pca15.der
+TEST_FILES = plain-1.cms.asc \
+ plain-2.cms.asc \
+ plain-3.cms.asc \
+ plain-large.cms.asc
+
+EXTRA_DIST = $(XTESTS) $(KEYS) $(CERTS) $(TEST_FILES) \
+ gpgsm-defs.scm run-tests.scm setup.scm all-tests.scm
+
+CLEANFILES = *.log report.xml
+
+# We need to depend on a couple of programs so that the tests don't
+# start before all programs are built.
+all-local: $(required_pgms)
diff --git a/tests/gpgsm/Makefile.in b/tests/gpgsm/Makefile.in
new file mode 100644
index 0000000..69109fd
--- /dev/null
+++ b/tests/gpgsm/Makefile.in
@@ -0,0 +1,648 @@
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am - For tests/gpgme
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+# Process this file with automake to create Makefile.in
+
+# cmacros.am - C macro definitions
+# Copyright (C) 2004 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@HAVE_DOSISH_SYSTEM_FALSE@am__append_1 = -DGNUPG_BINDIR="\"$(bindir)\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_LIBEXECDIR="\"$(libexecdir)\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_LIBDIR="\"$(libdir)/@PACKAGE@\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_DATADIR="\"$(datadir)/@PACKAGE@\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_SYSCONFDIR="\"$(sysconfdir)/@PACKAGE@\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_LOCALSTATEDIR="\"$(localstatedir)\""
+
+
+# If a specific protect tool program has been defined, pass its name
+# to cc. Note that these macros should not be used directly but via
+# the gnupg_module_name function.
+@GNUPG_AGENT_PGM_TRUE@am__append_2 = -DGNUPG_DEFAULT_AGENT="\"@GNUPG_AGENT_PGM@\""
+@GNUPG_PINENTRY_PGM_TRUE@am__append_3 = -DGNUPG_DEFAULT_PINENTRY="\"@GNUPG_PINENTRY_PGM@\""
+@GNUPG_SCDAEMON_PGM_TRUE@am__append_4 = -DGNUPG_DEFAULT_SCDAEMON="\"@GNUPG_SCDAEMON_PGM@\""
+@GNUPG_DIRMNGR_PGM_TRUE@am__append_5 = -DGNUPG_DEFAULT_DIRMNGR="\"@GNUPG_DIRMNGR_PGM@\""
+@GNUPG_PROTECT_TOOL_PGM_TRUE@am__append_6 = -DGNUPG_DEFAULT_PROTECT_TOOL="\"@GNUPG_PROTECT_TOOL_PGM@\""
+@GNUPG_DIRMNGR_LDAP_PGM_TRUE@am__append_7 = -DGNUPG_DEFAULT_DIRMNGR_LDAP="\"@GNUPG_DIRMNGR_LDAP_PGM@\""
+subdir = tests/gpgsm
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/autobuild.m4 \
+ $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/ksba.m4 \
+ $(top_srcdir)/m4/lcmessage.m4 $(top_srcdir)/m4/ldap.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libassuan.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/npth.m4 $(top_srcdir)/m4/ntbtls.m4 \
+ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \
+ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/readline.m4 \
+ $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \
+ $(top_srcdir)/m4/tar-ustar.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/am/cmacros.am \
+ $(top_srcdir)/build-aux/mkinstalldirs
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+AWK_HEX_NUMBER_OPTION = @AWK_HEX_NUMBER_OPTION@
+BUILD_FILEVERSION = @BUILD_FILEVERSION@
+BUILD_HOSTNAME = @BUILD_HOSTNAME@
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+BUILD_REVISION = @BUILD_REVISION@
+BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
+BUILD_VERSION = @BUILD_VERSION@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DL_LIBS = @DL_LIBS@
+DNSLIBS = @DNSLIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENCFS = @ENCFS@
+EXEEXT = @EXEEXT@
+FUSERMOUNT = @FUSERMOUNT@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNUPG_AGENT_PGM = @GNUPG_AGENT_PGM@
+GNUPG_DIRMNGR_LDAP_PGM = @GNUPG_DIRMNGR_LDAP_PGM@
+GNUPG_DIRMNGR_PGM = @GNUPG_DIRMNGR_PGM@
+GNUPG_PINENTRY_PGM = @GNUPG_PINENTRY_PGM@
+GNUPG_PROTECT_TOOL_PGM = @GNUPG_PROTECT_TOOL_PGM@
+GNUPG_SCDAEMON_PGM = @GNUPG_SCDAEMON_PGM@
+GPGKEYS_LDAP = @GPGKEYS_LDAP@
+GPGRT_CONFIG = @GPGRT_CONFIG@
+GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
+GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
+GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
+GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
+GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+KSBA_CFLAGS = @KSBA_CFLAGS@
+KSBA_CONFIG = @KSBA_CONFIG@
+KSBA_LIBS = @KSBA_LIBS@
+LBER_LIBS = @LBER_LIBS@
+LDAPLIBS = @LDAPLIBS@
+LDAP_CPPFLAGS = @LDAP_CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
+LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
+LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@
+LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBREADLINE = @LIBREADLINE@
+LIBS = @LIBS@
+LIBUSB_CPPFLAGS = @LIBUSB_CPPFLAGS@
+LIBUSB_LIBS = @LIBUSB_LIBS@
+LIBUTIL_LIBS = @LIBUTIL_LIBS@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NETLIBS = @NETLIBS@
+NPTH_CFLAGS = @NPTH_CFLAGS@
+NPTH_CONFIG = @NPTH_CONFIG@
+NPTH_LIBS = @NPTH_LIBS@
+NTBTLS_CFLAGS = @NTBTLS_CFLAGS@
+NTBTLS_CONFIG = @NTBTLS_CONFIG@
+NTBTLS_LIBS = @NTBTLS_LIBS@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_GT = @PACKAGE_GT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SENDMAIL = @SENDMAIL@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHRED = @SHRED@
+SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
+SQLITE3_LIBS = @SQLITE3_LIBS@
+STRIP = @STRIP@
+SYSROOT = @SYSROOT@
+SYS_SOCKET_H = @SYS_SOCKET_H@
+TAR = @TAR@
+USE_C99_CFLAGS = @USE_C99_CFLAGS@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+W32SOCKLIBS = @W32SOCKLIBS@
+WINDRES = @WINDRES@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+YAT2M = @YAT2M@
+ZLIBS = @ZLIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = $(datadir)/locale
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# Programs required before we can run these tests.
+required_pgms = ../../g10/gpg$(EXEEXT) ../../agent/gpg-agent$(EXEEXT) \
+ ../../tools/gpg-connect-agent$(EXEEXT) \
+ ../gpgscm/gpgscm$(EXEEXT)
+
+
+# NB: AM_CFLAGS may also be used by tools running on the build
+# platform to create source files.
+AM_CPPFLAGS = -I$(top_srcdir)/common -DLOCALEDIR=\"$(localedir)\" \
+ $(am__append_1) $(am__append_2) $(am__append_3) \
+ $(am__append_4) $(am__append_5) $(am__append_6) \
+ $(am__append_7)
+@HAVE_W32CE_SYSTEM_FALSE@extra_sys_libs =
+
+# Under Windows we use LockFileEx. WindowsCE provides this only on
+# the WindowsMobile 6 platform and thus we need to use the coredll6
+# import library. We also want to use a stacksize of 256k instead of
+# the 2MB which is the default with cegcc. 256k is the largest stack
+# we use with pth.
+@HAVE_W32CE_SYSTEM_TRUE@extra_sys_libs = -lcoredll6
+@HAVE_W32CE_SYSTEM_FALSE@extra_bin_ldflags =
+@HAVE_W32CE_SYSTEM_TRUE@extra_bin_ldflags = -Wl,--stack=0x40000
+resource_objs =
+
+# Convenience macros
+libcommon = ../common/libcommon.a
+libcommonpth = ../common/libcommonpth.a
+libcommontls = ../common/libcommontls.a
+libcommontlsnpth = ../common/libcommontlsnpth.a
+AM_CFLAGS =
+TESTS_ENVIRONMENT = LC_ALL=C \
+ EXEEXT=$(EXEEXT) \
+ PATH="../gpgscm:$(PATH)" \
+ abs_top_srcdir="$(abs_top_srcdir)" \
+ objdir="$(abs_top_builddir)" \
+ GPGSCM_PATH="$(abs_top_srcdir)/tests/gpgscm"
+
+XTESTS = \
+ import.scm \
+ encrypt.scm \
+ verify.scm \
+ decrypt.scm \
+ sign.scm \
+ export.scm
+
+KEYS = 32100C27173EF6E9C4E9A25D3D69F86D37A4F939
+CERTS = cert_g10code_test1.der \
+ cert_dfn_pca01.der \
+ cert_dfn_pca15.der
+
+TEST_FILES = plain-1.cms.asc \
+ plain-2.cms.asc \
+ plain-3.cms.asc \
+ plain-large.cms.asc
+
+EXTRA_DIST = $(XTESTS) $(KEYS) $(CERTS) $(TEST_FILES) \
+ gpgsm-defs.scm run-tests.scm setup.scm all-tests.scm
+
+CLEANFILES = *.log report.xml
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .o .rc
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/am/cmacros.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/gpgsm/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu tests/gpgsm/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/am/cmacros.am $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile all-local
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am all-local check check-am clean clean-generic \
+ cscopelist-am ctags-am distclean distclean-generic distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+ pdf-am ps ps-am tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+@HAVE_W32_SYSTEM_TRUE@.rc.o:
+@HAVE_W32_SYSTEM_TRUE@ $(WINDRES) $(DEFAULT_INCLUDES) $(INCLUDES) "$<" "$@"
+
+# XXX: Currently, one cannot override automake's 'check' target. As a
+# workaround, we avoid defining 'TESTS', thus automake will not emit
+# the 'check' target. For extra robustness, we merely define a
+# dependency on 'xcheck', so this hack should also work even if
+# automake would emit the 'check' target, as adding dependencies to
+# targets is okay.
+check: xcheck
+
+.PHONY: xcheck
+xcheck:
+ $(TESTS_ENVIRONMENT) $(abs_top_builddir)/tests/gpgscm/gpgscm \
+ $(abs_srcdir)/run-tests.scm $(TESTFLAGS) $(TESTS)
+
+# We need to depend on a couple of programs so that the tests don't
+# start before all programs are built.
+all-local: $(required_pgms)
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tests/gpgsm/all-tests.scm b/tests/gpgsm/all-tests.scm
new file mode 100644
index 0000000..1baa924
--- /dev/null
+++ b/tests/gpgsm/all-tests.scm
@@ -0,0 +1,43 @@
+;; Copyright (C) 2017 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(export all-tests
+ ;; Parse the Makefile.am to find all tests.
+
+ (load (with-path "makefile.scm"))
+
+ (define (expander filename port key)
+ (parse-makefile port key))
+
+ (define (parse filename key)
+ (parse-makefile-expand filename expander key))
+
+ (define setup
+ (make-environment-cache
+ (test::scm
+ #f
+ (path-join "tests" "gpgsm" "setup.scm")
+ (in-srcdir "tests" "gpgsm" "setup.scm")
+ "--" "tests" "gpg")))
+
+ (map (lambda (name)
+ (test::scm setup
+ (path-join "tests" "gpgsm" name)
+ (in-srcdir "tests" "gpgsm" name)))
+ (parse-makefile-expand (in-srcdir "tests" "gpgsm" "Makefile.am")
+ (lambda (filename port key) (parse-makefile port key))
+ "XTESTS")))
diff --git a/tests/gpgsm/cert_dfn_pca01.der b/tests/gpgsm/cert_dfn_pca01.der
new file mode 100644
index 0000000..4c8593c
--- /dev/null
+++ b/tests/gpgsm/cert_dfn_pca01.der
Binary files differ
diff --git a/tests/gpgsm/cert_dfn_pca15.der b/tests/gpgsm/cert_dfn_pca15.der
new file mode 100644
index 0000000..c28f137
--- /dev/null
+++ b/tests/gpgsm/cert_dfn_pca15.der
Binary files differ
diff --git a/tests/gpgsm/cert_g10code_test1.der b/tests/gpgsm/cert_g10code_test1.der
new file mode 100644
index 0000000..67c7db6
--- /dev/null
+++ b/tests/gpgsm/cert_g10code_test1.der
Binary files differ
diff --git a/tests/gpgsm/decrypt.scm b/tests/gpgsm/decrypt.scm
new file mode 100644
index 0000000..c328ba8
--- /dev/null
+++ b/tests/gpgsm/decrypt.scm
@@ -0,0 +1,30 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "gpgsm" "gpgsm-defs.scm"))
+(setup-gpgsm-environment)
+
+(for-each-p
+ "Checking decryption of supplied files."
+ (lambda (name)
+ (tr:do
+ (tr:open (in-srcdir "tests" "gpgsm" (string-append name ".cms.asc")))
+ (tr:gpgsm "" '(--decrypt))
+ (tr:assert-identity name)))
+ plain-files)
diff --git a/tests/gpgsm/encrypt.scm b/tests/gpgsm/encrypt.scm
new file mode 100644
index 0000000..bb90c8e
--- /dev/null
+++ b/tests/gpgsm/encrypt.scm
@@ -0,0 +1,39 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "gpgsm" "gpgsm-defs.scm"))
+(setup-gpgsm-environment)
+
+(for-each-p
+ "Checking encryption"
+ (lambda (source)
+ (for-each-p
+ "with arguments..."
+ (lambda (args)
+ (tr:do
+ (tr:open source)
+ (tr:gpgsm "" `(--encrypt --recipient ,certs::test-1::uid::CN
+ ,@args))
+ (tr:gpgsm "" `(--decrypt ,@(if (member '--base64 args)
+ '(--assume-base64) '())))
+ (tr:assert-identity source)))
+ `(()
+ (--armor --cipher-algo ,(cadr (force all-cipher-algos)))
+ (--base64 --digest-algo ,(car (force all-hash-algos))))))
+ all-files)
diff --git a/tests/gpgsm/export.scm b/tests/gpgsm/export.scm
new file mode 100644
index 0000000..4a8108b
--- /dev/null
+++ b/tests/gpgsm/export.scm
@@ -0,0 +1,32 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "gpgsm" "gpgsm-defs.scm"))
+(setup-gpgsm-environment)
+
+(for-each-p'
+ "Checking certificate export."
+ (lambda (cert)
+ (lettmp (exported)
+ (call-check `(,@gpgsm --output ,exported --export ,cert::uid::CN))
+ (with-ephemeral-home-directory setup-gpgsm-environment-no-atexit stop-agent
+ (call-check `(,@gpgsm --import ,exported))
+ (assert (sm-have-public-key? cert)))))
+ (lambda (cert) cert::uid::CN)
+ all-certs)
diff --git a/tests/gpgsm/gpgsm-defs.scm b/tests/gpgsm/gpgsm-defs.scm
new file mode 100644
index 0000000..848bc75
--- /dev/null
+++ b/tests/gpgsm/gpgsm-defs.scm
@@ -0,0 +1,104 @@
+;; Common definitions for the GPGSM test scripts.
+;;
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+
+;; This is the list of certificates that we install in the test
+;; environment.
+(define certs
+ (package
+ (define (new fpr issuer-fpr uid)
+ (package))
+ (define (new-uid CN OU O L C)
+ (package))
+ (define test-1 (new "3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E"
+ "3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E"
+ (new-uid "test cert 1"
+ "Aegypten Project"
+ "g10 Code GmbH"
+ "Düsseldorf"
+ "DE")))))
+(define all-certs (list certs::test-1))
+
+(define gpgsm `(,(tool 'gpgsm) --yes)) ;; more/less options
+
+(define (tr:gpgsm input args)
+ (tr:spawn input `(,@gpgsm --output **out** ,@args **in**)))
+
+(define (pipe:gpgsm args)
+ (pipe:spawn `(,@gpgsm --output - ,@args -)))
+
+(define (gpgsm-with-colons args)
+ (let ((s (call-popen `(,@gpgsm --with-colons ,@args) "")))
+ (map (lambda (line) (string-split line #\:))
+ (string-split-newlines s))))
+
+(define (sm-have-public-key? key)
+ (catch #f
+ (pair? (filter (lambda (l) (and (equal? 'fpr (:type l))
+ (equal? key::fpr (:fpr l))))
+ (gpgsm-with-colons `(--list-keys ,key::fpr))))))
+
+(define (sm-have-secret-key? key)
+ (catch #f
+ (pair? (filter (lambda (l) (and (equal? 'fpr (:type l))
+ (equal? key::fpr (:fpr l))))
+ (gpgsm-with-colons `(--list-secret-keys ,key::fpr))))))
+
+(define (create-gpgsmhome)
+ (create-file "gpgsm.conf"
+ "disable-crl-checks"
+ "faked-system-time 1008241200")
+ (create-file "gpg-agent.conf"
+ (string-append "pinentry-program " (tool 'pinentry))
+ "disable-scdaemon")
+ (start-agent)
+ (create-file
+ "trustlist.txt"
+ "32100C27173EF6E9C4E9A25D3D69F86D37A4F939"
+ "# CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=Düsseldorf,C=DE"
+ "3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E S")
+
+ (log "Storing private keys")
+ (for-each
+ (lambda (name)
+ (file-copy (in-srcdir "tests" "gpgsm" name)
+ (path-join "private-keys-v1.d"
+ (string-append name ".key"))))
+ '("32100C27173EF6E9C4E9A25D3D69F86D37A4F939"))
+
+ (log "Importing public demo and test keys")
+ (call-check `(,@gpgsm --import ,(in-srcdir "tests" "gpgsm" "cert_g10code_test1.der")))
+
+ (create-sample-files)
+ (stop-agent))
+
+;; Initialize the test environment, install appropriate configuration
+;; and start the agent, with the keys from the legacy test suite.
+(define (setup-gpgsm-environment)
+ (if (member "--unpack-tarball" *args*)
+ (call-check `(,(tool 'gpgtar) --extract --directory=. ,(cadr *args*)))
+ (create-gpgsm-gpghome))
+ (start-agent))
+
+(define (setup-gpgsm-environment-no-atexit)
+ (if (member "--unpack-tarball" *args*)
+ (call-check `(,(tool 'gpgtar) --extract --directory=. ,(cadr *args*)))
+ (create-gpgsm-gpghome))
+ (start-agent #t))
diff --git a/tests/gpgsm/import.scm b/tests/gpgsm/import.scm
new file mode 100644
index 0000000..be555da
--- /dev/null
+++ b/tests/gpgsm/import.scm
@@ -0,0 +1,53 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "gpgsm" "gpgsm-defs.scm"))
+(setup-gpgsm-environment)
+
+(define certs-for-import
+ (list (list "cert_dfn_pca01.der"
+ (certs::new
+ "DFA56FB5FC41E3A8921F77AD1622EEFD9152A5AD"
+ "DFA56FB5FC41E3A8921F77AD1622EEFD9152A5AD"
+ (certs::new-uid "DFN Top Level Certification Authority"
+ "DFN-PCA"
+ "Deutsches Forschungsnetz"
+ ""
+ "DE")))
+ (list "cert_dfn_pca15.der"
+ (certs::new
+ "2C8F3C356AB761CB3674835B792CDA52937F9285"
+ "DFA56FB5FC41E3A8921F77AD1622EEFD9152A5AD"
+ (certs::new-uid "DFN Server Certification Authority"
+ "DFN-PCA"
+ "Deutsches Forschungsnetz"
+ ""
+ "DE")))))
+
+(define :name car)
+(define :cert cadr)
+
+(for-each-p'
+ "Checking certificate import."
+ (lambda (test)
+ (assert (not (sm-have-public-key? (:cert test))))
+ (call-check `(,@gpgsm --import ,(in-srcdir "tests" "gpgsm" (:name test))))
+ (assert (sm-have-public-key? (:cert test))))
+ (lambda (test) (:name test))
+ certs-for-import)
diff --git a/tests/gpgsm/plain-1.cms.asc b/tests/gpgsm/plain-1.cms.asc
new file mode 100644
index 0000000..cb1a4db
--- /dev/null
+++ b/tests/gpgsm/plain-1.cms.asc
@@ -0,0 +1,33 @@
+-----BEGIN ENCRYPTED MESSAGE-----
+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
+-----END ENCRYPTED MESSAGE-----
diff --git a/tests/gpgsm/plain-2.cms.asc b/tests/gpgsm/plain-2.cms.asc
new file mode 100644
index 0000000..1ff0a8f
--- /dev/null
+++ b/tests/gpgsm/plain-2.cms.asc
@@ -0,0 +1,43 @@
+-----BEGIN ENCRYPTED MESSAGE-----
+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
+AA==
+-----END ENCRYPTED MESSAGE-----
diff --git a/tests/gpgsm/plain-3.cms.asc b/tests/gpgsm/plain-3.cms.asc
new file mode 100644
index 0000000..5c6331c
--- /dev/null
+++ b/tests/gpgsm/plain-3.cms.asc
@@ -0,0 +1,11 @@
+-----BEGIN ENCRYPTED MESSAGE-----
+MIAGCSqGSIb3DQEHA6CAMIACAQAxggELMIIBBwIBADBwMGsxCzAJBgNVBAYTAkRF
+MRMwEQYDVQQHFApE/HNzZWxkb3JmMRYwFAYDVQQKEw1nMTAgQ29kZSBHbWJIMRkw
+FwYDVQQLExBBZWd5cHRlbiBQcm9qZWN0MRQwEgYDVQQDEwt0ZXN0IGNlcnQgMQIB
+ADANBgkqhkiG9w0BAQEFAASBgB8adQNvg/lKghatZ/Wy+tMUrarqYmTHB3SDKoDh
+B+riZDDxj/j/xR6utjmukvrAz6gz3BzKxU+AjAmXLpNesN1kv+oDS2DmAluFzg5e
+j/Ppo+Dudq2uJjZOsMry6xniMIwOhHsLhkLs2cuEb0eB6XAVfMzJvdTawuLaMeLN
+fGmVMIAGCSqGSIb3DQEHATAdBglghkgBZQMEAQIEECIzN1lVNsKXkPAEySzCpUWg
+gAQgzfoRhxREyicy4Vf6dfDJ+X4kaB4tGwsKGKYVV1uITjEEEFpk2DxEsIIxH66o
+pfqG9W4AAAAAAAAAAAAA
+-----END ENCRYPTED MESSAGE-----
diff --git a/tests/gpgsm/plain-large.cms.asc b/tests/gpgsm/plain-large.cms.asc
new file mode 100644
index 0000000..f8fc90f
--- /dev/null
+++ b/tests/gpgsm/plain-large.cms.asc
@@ -0,0 +1,4213 @@
+-----BEGIN ENCRYPTED MESSAGE-----
+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
+AAAAAAA=
+-----END ENCRYPTED MESSAGE-----
diff --git a/tests/gpgsm/run-tests.scm b/tests/gpgsm/run-tests.scm
new file mode 100644
index 0000000..6b460b1
--- /dev/null
+++ b/tests/gpgsm/run-tests.scm
@@ -0,0 +1,39 @@
+;; Test-suite runner.
+;;
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(if (string=? "" (getenv "abs_top_srcdir"))
+ (begin
+ (echo "Environment variable 'abs_top_srcdir' not set. Please point it to"
+ "tests/gpgsm.")
+ (exit 2)))
+
+(define tests (filter (lambda (arg) (not (string-prefix? arg "--"))) *args*))
+
+(define setup
+ (make-environment-cache (test::scm
+ #f
+ (path-join "tests" "gpgsm" "setup.scm")
+ (in-srcdir "tests" "gpgsm" "setup.scm"))))
+
+(run-tests (if (null? tests)
+ (load-tests "tests" "gpgsm")
+ (map (lambda (name)
+ (test::scm setup
+ (path-join "tests" "gpgsm" name)
+ (in-srcdir "tests" "gpgsm" name))) tests)))
diff --git a/tests/gpgsm/setup.scm b/tests/gpgsm/setup.scm
new file mode 100644
index 0000000..c241b38
--- /dev/null
+++ b/tests/gpgsm/setup.scm
@@ -0,0 +1,28 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "gpgsm" "gpgsm-defs.scm"))
+
+(define tarball (flag "--create-tarball" *args*))
+(unless (and tarball (not (null? tarball)))
+ (error "Usage: setup.scm --create-tarball <file> ..."))
+
+(setenv "GNUPGHOME" (getcwd) #t)
+(create-gpgsmhome)
+(call-check `(,(tool 'gpgtar) --create --output ,(car tarball) "."))
diff --git a/tests/gpgsm/sign.scm b/tests/gpgsm/sign.scm
new file mode 100644
index 0000000..48b7b06
--- /dev/null
+++ b/tests/gpgsm/sign.scm
@@ -0,0 +1,35 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "gpgsm" "gpgsm-defs.scm"))
+(setup-gpgsm-environment)
+
+(for-each-p
+ "Checking signing."
+ (lambda (source)
+ (for-each-p
+ "with digest..."
+ (lambda (digest)
+ (tr:do
+ (tr:open source)
+ (tr:gpgsm "" `(--sign --digest-algo ,digest))
+ (tr:gpgsm "" '(--verify))
+ (tr:assert-identity source)))
+ (force all-hash-algos)))
+ all-files)
diff --git a/tests/gpgsm/verify.scm b/tests/gpgsm/verify.scm
new file mode 100644
index 0000000..40dbd48
--- /dev/null
+++ b/tests/gpgsm/verify.scm
@@ -0,0 +1,65 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "gpgsm" "gpgsm-defs.scm"))
+(setup-gpgsm-environment)
+
+;;
+;; Two simple tests to check that verify fails for bad input data
+;;
+(for-each-p
+ "Checking bogus signature."
+ (lambda (char)
+ (lettmp (x)
+ (call-with-binary-output-file
+ x
+ (lambda (port)
+ (display (make-string 64 (integer->char (string->number char)))
+ port)))
+ (assert (not (zero? (call `(,@gpgsm --verify ,x data-500)))))))
+ '("#x2d" "#xca"))
+
+(define test-text1 "Hallo Leute!\n")
+(define test-text1f "Hallo Leute?\n")
+(define test-sig1 "
+-----BEGIN CMS OBJECT-----
+MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAA
+MYIBOTCCATUCAQEwcDBrMQswCQYDVQQGEwJERTETMBEGA1UEBxQKRPxzc2VsZG9y
+ZjEWMBQGA1UEChMNZzEwIENvZGUgR21iSDEZMBcGA1UECxMQQWVneXB0ZW4gUHJv
+amVjdDEUMBIGA1UEAxMLdGVzdCBjZXJ0IDECAQAwBwYFKw4DAhqgJTAjBgkqhkiG
+9w0BCQQxFgQU7FC/ibH3lC9GE24RJJxa8zqP7wEwCwYJKoZIhvcNAQEBBIGAA3oC
+DUmKERmD1eoJYFw38y/qnncS/6ZPjWINDIphZeK8mzAANpvpIaRPf3sNBznb89QF
+mRgCXIWcjlHT0DTRLBf192Ve22IyKH00L52CqFsSN3a2sajqRUlXH8RY2D+Al71e
+MYdRclgjObCcoilA8fZ13VR4DiMJVFCxJL4qVWI=
+-----END CMS OBJECT-----")
+
+;;
+;; Now run the tests.
+;;
+(info "Checking that a valid signature is verified as such.")
+(lettmp (sig body)
+ (call-with-binary-output-file sig (lambda (port) (display test-sig1 port)))
+ (call-with-binary-output-file body (lambda (port) (display test-text1 port)))
+ (call-check `(,@gpgsm --verify ,sig ,body)))
+
+(info "Checking that an invalid signature is verified as such.")
+(lettmp (sig body)
+ (call-with-binary-output-file sig (lambda (port) (display test-sig1 port)))
+ (call-with-binary-output-file body (lambda (port) (display test-text1f port)))
+ (assert (not (zero? (call `(,@gpgsm --verify ,sig ,body))))))
diff --git a/tests/inittests b/tests/inittests
new file mode 100755
index 0000000..9090674
--- /dev/null
+++ b/tests/inittests
@@ -0,0 +1,100 @@
+#!/bin/sh
+# Copyright (C) 2002 Free Software Foundation, Inc.
+#
+# This file is free software; as a special exception the author gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+set -e
+
+sample_certs='
+cert_g10code_test1.pem
+cert_g10code_pete1.pem
+cert_g10code_theo1.pem
+'
+
+private_keys='
+32100C27173EF6E9C4E9A25D3D69F86D37A4F939
+'
+
+clean_files='
+gpgsm.conf gpg-agent.conf trustlist.txt pubring.kbx
+msg msg.sig msg.unsig
+'
+
+
+[ -z "$srcdir" ] && srcdir=.
+[ -z "$GPGSM" ] && GPGSM=../sm/gpgsm
+
+if [ -d $srcdir/samplekeys ] \
+ && grep TESTS_ENVIRONMENT Makefile >/dev/null 2>&1; then
+ :
+else
+ # During make distclean the Makefile has already been removed,
+ # so we need this extra test.
+ if ! grep gnupg-test-directory testdir.stamp >/dev/null 2>&1; then
+ echo "inittests: please cd to the tests directory first" >&2
+ exit 1
+ fi
+fi
+
+if [ "$1" = "--clean" ]; then
+ if [ -d private-keys-v1.d ]; then
+ rm private-keys-v1.d/* 2>/dev/null || true
+ rmdir private-keys-v1.d
+ fi
+ rm ${clean_files} testdir.stamp 2>/dev/null || true
+ exit 0
+fi
+
+if [ "$GNUPGHOME" != "`/bin/pwd`" ]; then
+ echo "inittests: please set GNUPGHOME to the test directory" >&2
+ exit 1
+fi
+
+if [ -n "$GPG_AGENT_INFO" ]; then
+ echo "inittests: please unset GPG_AGENT_INFO" >&2
+ exit 1
+fi
+
+# A stamp file used with --clean
+echo gnupg-test-directory > testdir.stamp
+
+
+# Create the private key directly if it does not exists and copy
+# the sample keys.
+[ -d private-keys-v1.d ] || mkdir private-keys-v1.d
+for i in ${private_keys}; do
+ cat ${srcdir}/samplekeys/$i.key >private-keys-v1.d/$i.key
+done
+
+# Create the configuration scripts
+# Note, die to an expired test certificate, we need to use
+# the faked system time option.
+cat > gpgsm.conf <<EOF
+no-secmem-warning
+disable-crl-checks
+agent-program ../agent/gpg-agent
+faked-system-time 1038835799
+EOF
+
+cat > gpg-agent.conf <<EOF
+no-grab
+pinentry-program /home/wk/work/pinentry/gtk/pinentry-gtk
+disable-scdaemon
+EOF
+
+cat > trustlist.txt <<EOF
+# CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=Düsseldorf,C=DE
+3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E S
+EOF
+
+# Make sure that the sample certs are available but ignore errors here
+# because we are not a test script.
+for i in ${sample_certs}; do
+ $GPGSM --import ${srcdir}/samplekeys/$i || true
+done
diff --git a/tests/migrations/Makefile.am b/tests/migrations/Makefile.am
new file mode 100644
index 0000000..6d2d2e8
--- /dev/null
+++ b/tests/migrations/Makefile.am
@@ -0,0 +1,66 @@
+# Makefile.am - For tests/openpgp
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+# Process this file with automake to create Makefile.in
+
+
+# Programs required before we can run these tests.
+required_pgms = ../../g10/gpg$(EXEEXT) ../../agent/gpg-agent$(EXEEXT) \
+ ../../tools/gpgtar$(EXEEXT) \
+ ../gpgscm/gpgscm$(EXEEXT)
+
+AM_CPPFLAGS = -I$(top_srcdir)/common
+include $(top_srcdir)/am/cmacros.am
+
+AM_CFLAGS =
+
+TESTS_ENVIRONMENT = GPG_AGENT_INFO= LC_ALL=C \
+ EXEEXT=$(EXEEXT) \
+ PATH="../gpgscm:$(PATH)" \
+ abs_top_srcdir="$(abs_top_srcdir)" \
+ objdir="$(abs_top_builddir)" \
+ GPGSCM_PATH="$(abs_top_srcdir)/tests/gpgscm"
+
+XTESTS = from-classic.scm \
+ extended-pkf.scm \
+ issue2276.scm
+
+TEST_FILES = from-classic.tar.asc \
+ extended-pkf.tar.asc \
+ issue2276.tar.asc
+
+# XXX: Currently, one cannot override automake's 'check' target. As a
+# workaround, we avoid defining 'TESTS', thus automake will not emit
+# the 'check' target. For extra robustness, we merely define a
+# dependency on 'xcheck', so this hack should also work even if
+# automake would emit the 'check' target, as adding dependencies to
+# targets is okay.
+check: xcheck
+
+.PHONY: xcheck
+xcheck:
+ $(TESTS_ENVIRONMENT) $(abs_top_builddir)/tests/gpgscm/gpgscm \
+ $(abs_srcdir)/run-tests.scm $(TESTFLAGS) $(TESTS)
+
+EXTRA_DIST = common.scm run-tests.scm setup.scm all-tests.scm \
+ $(XTESTS) $(TEST_FILES)
+
+CLEANFILES = *.log report.xml
+
+# We need to depend on a couple of programs so that the tests don't
+# start before all programs are built.
+all-local: $(required_pgms)
diff --git a/tests/migrations/Makefile.in b/tests/migrations/Makefile.in
new file mode 100644
index 0000000..0cc6786
--- /dev/null
+++ b/tests/migrations/Makefile.in
@@ -0,0 +1,638 @@
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am - For tests/openpgp
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+# Process this file with automake to create Makefile.in
+
+# cmacros.am - C macro definitions
+# Copyright (C) 2004 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@HAVE_DOSISH_SYSTEM_FALSE@am__append_1 = -DGNUPG_BINDIR="\"$(bindir)\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_LIBEXECDIR="\"$(libexecdir)\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_LIBDIR="\"$(libdir)/@PACKAGE@\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_DATADIR="\"$(datadir)/@PACKAGE@\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_SYSCONFDIR="\"$(sysconfdir)/@PACKAGE@\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_LOCALSTATEDIR="\"$(localstatedir)\""
+
+
+# If a specific protect tool program has been defined, pass its name
+# to cc. Note that these macros should not be used directly but via
+# the gnupg_module_name function.
+@GNUPG_AGENT_PGM_TRUE@am__append_2 = -DGNUPG_DEFAULT_AGENT="\"@GNUPG_AGENT_PGM@\""
+@GNUPG_PINENTRY_PGM_TRUE@am__append_3 = -DGNUPG_DEFAULT_PINENTRY="\"@GNUPG_PINENTRY_PGM@\""
+@GNUPG_SCDAEMON_PGM_TRUE@am__append_4 = -DGNUPG_DEFAULT_SCDAEMON="\"@GNUPG_SCDAEMON_PGM@\""
+@GNUPG_DIRMNGR_PGM_TRUE@am__append_5 = -DGNUPG_DEFAULT_DIRMNGR="\"@GNUPG_DIRMNGR_PGM@\""
+@GNUPG_PROTECT_TOOL_PGM_TRUE@am__append_6 = -DGNUPG_DEFAULT_PROTECT_TOOL="\"@GNUPG_PROTECT_TOOL_PGM@\""
+@GNUPG_DIRMNGR_LDAP_PGM_TRUE@am__append_7 = -DGNUPG_DEFAULT_DIRMNGR_LDAP="\"@GNUPG_DIRMNGR_LDAP_PGM@\""
+subdir = tests/migrations
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/autobuild.m4 \
+ $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/ksba.m4 \
+ $(top_srcdir)/m4/lcmessage.m4 $(top_srcdir)/m4/ldap.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libassuan.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/npth.m4 $(top_srcdir)/m4/ntbtls.m4 \
+ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \
+ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/readline.m4 \
+ $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \
+ $(top_srcdir)/m4/tar-ustar.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/am/cmacros.am \
+ $(top_srcdir)/build-aux/mkinstalldirs
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+AWK_HEX_NUMBER_OPTION = @AWK_HEX_NUMBER_OPTION@
+BUILD_FILEVERSION = @BUILD_FILEVERSION@
+BUILD_HOSTNAME = @BUILD_HOSTNAME@
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+BUILD_REVISION = @BUILD_REVISION@
+BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
+BUILD_VERSION = @BUILD_VERSION@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DL_LIBS = @DL_LIBS@
+DNSLIBS = @DNSLIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENCFS = @ENCFS@
+EXEEXT = @EXEEXT@
+FUSERMOUNT = @FUSERMOUNT@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNUPG_AGENT_PGM = @GNUPG_AGENT_PGM@
+GNUPG_DIRMNGR_LDAP_PGM = @GNUPG_DIRMNGR_LDAP_PGM@
+GNUPG_DIRMNGR_PGM = @GNUPG_DIRMNGR_PGM@
+GNUPG_PINENTRY_PGM = @GNUPG_PINENTRY_PGM@
+GNUPG_PROTECT_TOOL_PGM = @GNUPG_PROTECT_TOOL_PGM@
+GNUPG_SCDAEMON_PGM = @GNUPG_SCDAEMON_PGM@
+GPGKEYS_LDAP = @GPGKEYS_LDAP@
+GPGRT_CONFIG = @GPGRT_CONFIG@
+GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
+GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
+GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
+GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
+GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+KSBA_CFLAGS = @KSBA_CFLAGS@
+KSBA_CONFIG = @KSBA_CONFIG@
+KSBA_LIBS = @KSBA_LIBS@
+LBER_LIBS = @LBER_LIBS@
+LDAPLIBS = @LDAPLIBS@
+LDAP_CPPFLAGS = @LDAP_CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
+LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
+LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@
+LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBREADLINE = @LIBREADLINE@
+LIBS = @LIBS@
+LIBUSB_CPPFLAGS = @LIBUSB_CPPFLAGS@
+LIBUSB_LIBS = @LIBUSB_LIBS@
+LIBUTIL_LIBS = @LIBUTIL_LIBS@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NETLIBS = @NETLIBS@
+NPTH_CFLAGS = @NPTH_CFLAGS@
+NPTH_CONFIG = @NPTH_CONFIG@
+NPTH_LIBS = @NPTH_LIBS@
+NTBTLS_CFLAGS = @NTBTLS_CFLAGS@
+NTBTLS_CONFIG = @NTBTLS_CONFIG@
+NTBTLS_LIBS = @NTBTLS_LIBS@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_GT = @PACKAGE_GT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SENDMAIL = @SENDMAIL@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHRED = @SHRED@
+SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
+SQLITE3_LIBS = @SQLITE3_LIBS@
+STRIP = @STRIP@
+SYSROOT = @SYSROOT@
+SYS_SOCKET_H = @SYS_SOCKET_H@
+TAR = @TAR@
+USE_C99_CFLAGS = @USE_C99_CFLAGS@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+W32SOCKLIBS = @W32SOCKLIBS@
+WINDRES = @WINDRES@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+YAT2M = @YAT2M@
+ZLIBS = @ZLIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = $(datadir)/locale
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# Programs required before we can run these tests.
+required_pgms = ../../g10/gpg$(EXEEXT) ../../agent/gpg-agent$(EXEEXT) \
+ ../../tools/gpgtar$(EXEEXT) \
+ ../gpgscm/gpgscm$(EXEEXT)
+
+
+# NB: AM_CFLAGS may also be used by tools running on the build
+# platform to create source files.
+AM_CPPFLAGS = -I$(top_srcdir)/common -DLOCALEDIR=\"$(localedir)\" \
+ $(am__append_1) $(am__append_2) $(am__append_3) \
+ $(am__append_4) $(am__append_5) $(am__append_6) \
+ $(am__append_7)
+@HAVE_W32CE_SYSTEM_FALSE@extra_sys_libs =
+
+# Under Windows we use LockFileEx. WindowsCE provides this only on
+# the WindowsMobile 6 platform and thus we need to use the coredll6
+# import library. We also want to use a stacksize of 256k instead of
+# the 2MB which is the default with cegcc. 256k is the largest stack
+# we use with pth.
+@HAVE_W32CE_SYSTEM_TRUE@extra_sys_libs = -lcoredll6
+@HAVE_W32CE_SYSTEM_FALSE@extra_bin_ldflags =
+@HAVE_W32CE_SYSTEM_TRUE@extra_bin_ldflags = -Wl,--stack=0x40000
+resource_objs =
+
+# Convenience macros
+libcommon = ../common/libcommon.a
+libcommonpth = ../common/libcommonpth.a
+libcommontls = ../common/libcommontls.a
+libcommontlsnpth = ../common/libcommontlsnpth.a
+AM_CFLAGS =
+TESTS_ENVIRONMENT = GPG_AGENT_INFO= LC_ALL=C \
+ EXEEXT=$(EXEEXT) \
+ PATH="../gpgscm:$(PATH)" \
+ abs_top_srcdir="$(abs_top_srcdir)" \
+ objdir="$(abs_top_builddir)" \
+ GPGSCM_PATH="$(abs_top_srcdir)/tests/gpgscm"
+
+XTESTS = from-classic.scm \
+ extended-pkf.scm \
+ issue2276.scm
+
+TEST_FILES = from-classic.tar.asc \
+ extended-pkf.tar.asc \
+ issue2276.tar.asc
+
+EXTRA_DIST = common.scm run-tests.scm setup.scm all-tests.scm \
+ $(XTESTS) $(TEST_FILES)
+
+CLEANFILES = *.log report.xml
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .o .rc
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/am/cmacros.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/migrations/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu tests/migrations/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/am/cmacros.am $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile all-local
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am all-local check check-am clean clean-generic \
+ cscopelist-am ctags-am distclean distclean-generic distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+ pdf-am ps ps-am tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+@HAVE_W32_SYSTEM_TRUE@.rc.o:
+@HAVE_W32_SYSTEM_TRUE@ $(WINDRES) $(DEFAULT_INCLUDES) $(INCLUDES) "$<" "$@"
+
+# XXX: Currently, one cannot override automake's 'check' target. As a
+# workaround, we avoid defining 'TESTS', thus automake will not emit
+# the 'check' target. For extra robustness, we merely define a
+# dependency on 'xcheck', so this hack should also work even if
+# automake would emit the 'check' target, as adding dependencies to
+# targets is okay.
+check: xcheck
+
+.PHONY: xcheck
+xcheck:
+ $(TESTS_ENVIRONMENT) $(abs_top_builddir)/tests/gpgscm/gpgscm \
+ $(abs_srcdir)/run-tests.scm $(TESTFLAGS) $(TESTS)
+
+# We need to depend on a couple of programs so that the tests don't
+# start before all programs are built.
+all-local: $(required_pgms)
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tests/migrations/all-tests.scm b/tests/migrations/all-tests.scm
new file mode 100644
index 0000000..421f696
--- /dev/null
+++ b/tests/migrations/all-tests.scm
@@ -0,0 +1,35 @@
+;; Copyright (C) 2017 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(export all-tests
+ ;; Parse the Makefile.am to find all tests.
+
+ (load (with-path "makefile.scm"))
+
+ (define (expander filename port key)
+ (parse-makefile port key))
+
+ (define (parse filename key)
+ (parse-makefile-expand filename expander key))
+
+ (map (lambda (name)
+ (test::scm #f
+ (path-join "tests" "migrations" name)
+ (in-srcdir "tests" "migrations" name)))
+ (parse-makefile-expand (in-srcdir "tests" "migrations" "Makefile.am")
+ (lambda (filename port key) (parse-makefile port key))
+ "XTESTS")))
diff --git a/tests/migrations/common.scm b/tests/migrations/common.scm
new file mode 100644
index 0000000..cabfdff
--- /dev/null
+++ b/tests/migrations/common.scm
@@ -0,0 +1,61 @@
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(if (string=? "" (getenv "abs_top_srcdir"))
+ (error "not called from make"))
+
+(let ((verbose (string->number (getenv "verbose"))))
+ (if (number? verbose)
+ (*set-verbose!* verbose)))
+
+(define (qualify executable)
+ (string-append executable (getenv "EXEEXT")))
+
+;; We may not use a relative name for gpg-agent.
+(define gpgconf (path-join (getenv "objdir") "tools" (qualify "gpgconf")))
+(define GPG-AGENT (path-join (getenv "objdir") "agent" (qualify "gpg-agent")))
+(define GPG `(,(path-join (getenv "objdir") "g10" (qualify "gpg"))
+ --no-permission-warning --no-greeting
+ --no-secmem-warning --batch
+ ,(string-append "--agent-program=" GPG-AGENT
+ "|--debug-quick-random")))
+(define GPG-no-batch
+ (filter (lambda (arg) (not (equal? arg '--batch))) GPG))
+
+(define GPGTAR (path-join (getenv "objdir") "tools" (qualify "gpgtar")))
+
+(define (untar-armored source-name)
+ (with-ephemeral-home-directory (lambda ()) (lambda ())
+ (pipe:do
+ (pipe:open source-name (logior O_RDONLY O_BINARY))
+ (pipe:spawn `(,@GPG --dearmor))
+ (pipe:spawn `(,GPGTAR --extract --directory=. -)))))
+
+(define (run-test message src-tarball test)
+ (catch (skip "gpgtar not built")
+ (call-check `(,GPGTAR --help)))
+
+ (with-temporary-working-directory
+ (info message)
+ (untar-armored src-tarball)
+ (setenv "GNUPGHOME" (getcwd) #t)
+
+ (catch (log "Warning: Creating socket directory failed:" (car *error*))
+ (call-popen `(,gpgconf --create-socketdir) ""))
+ (test (getcwd))
+ (catch (log "Warning: Removing socket directory failed.")
+ (call-popen `(,gpgconf --remove-socketdir) ""))))
diff --git a/tests/migrations/extended-pkf.scm b/tests/migrations/extended-pkf.scm
new file mode 100755
index 0000000..cc1a074
--- /dev/null
+++ b/tests/migrations/extended-pkf.scm
@@ -0,0 +1,38 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "migrations" "common.scm"))
+
+(catch (skip "gpgtar not built")
+ (call-check `(,GPGTAR --help)))
+
+(define (assert-keys-usable)
+ (for-each
+ (lambda (keyid)
+ (catch (error "Key not found:" keyid)
+ (call-check `(,@GPG --list-secret-keys ,keyid))))
+ '("C40FDECF" "ECABF51D")))
+
+(run-test
+ "Testing the extended private key format ..."
+ (in-srcdir "tests" "migrations" "extended-pkf.tar.asc")
+ (lambda (gpghome)
+ (assert-keys-usable)))
+
+;; XXX try changing a key, and check that the format is not changed.
diff --git a/tests/migrations/extended-pkf.tar.asc b/tests/migrations/extended-pkf.tar.asc
new file mode 100644
index 0000000..adbe174
--- /dev/null
+++ b/tests/migrations/extended-pkf.tar.asc
@@ -0,0 +1,220 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+cHJpdmF0ZS1rZXlzLXYxLmQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAADAwMDA3NTUAMDAwMTc1MAAwMDAxNzUwADAwMDAwMDAwMDAwADEyNzM2NzI1
+MzA2ADAxNDU0NwAgNQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAB1c3RhcgAwMHRleXRob29uAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAdGV5dGhvb24AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwcml2YXRlLWtleXMtdjEu
+ZC84QjVBQkYzRUY5RUI4RDk2QjkxQTBCOEMyQzQ0MDFDOTFDODM0QzM0LmtleQAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwMDY0NAAwMDAx
+NzUwADAwMDE3NTAAMDAwMDAwMDEyMDQAMTI3MzY3MjUyNTYAMDIyMTAyACAwAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AHVzdGFyADAwdGV5dGhvb24AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0ZXl0aG9v
+bgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAEtleTogKHByaXZhdGUta2V5IChlbGcgKHAgIzAwQ0NE
+OEIxRjlEQUM3NEQ4MDhDQzUyRjBEODk0NjREQTU1NEM2OUQ2N0YzCiAzMjNDNDJB
+OTVDOTk2MkRGNDIxMjZFQzBFMDk3MUY0OUI4MTE1MjlBNkEyQUU5RjBBREVCODM5
+QTYzNDYxNUNENTZGQTU0CiBGNUEwQjdFRjI1QTBFMkZFODQzRkEyRTZFMDIxQ0FC
+NDExOUU2MDM5NEM5RDZBM0Y3QUQ0RjU3Nzk2RDM2NjY5QTUxMjY2CiBDMjdBOEQx
+QzVBNkI0MTQxRDVDODMxRTg0NTQxRjNDODExRTg5MDc4OTgwMzM4Mjk1RjgyQjdG
+N0ZENDMzM0VGRDkzMzEyCiBGMkFCIykoZyAjMDYjKSh5ICMzNzczQTZEOUVDODg5
+RDc2RTMyNEQ2RTVFQzIxQkQ0NTY5OTgzMUFFNEZEMEFFMDM3ODIwCiA1QkFFNUI4
+Q0U4NUZBREFCRDdFNkI3QzczMDI1Q0IzRDczMEQ1QzU4MjkwMzRENzZCRTA4NTVD
+MkU5RkY3QTQ5MjNFRkZBCiBGMTZBOTY2Njk0NERCQzYyOTQ4MzhGQzNGMDlGRjk2
+NEE4RDAyM0NCOEVCQTMzMkZCMDUxRUEwMjgyMEVFNjEyMEZGQkU2CiAyQjM2QTIw
+MkIzQzc1MkY5REE3NkIyRUMxMUE2N0QyRTM1RTY2RUMxMDYzNTg3QjIyNTAwRThB
+NDZEMTU3Qjc1IykoeCAjCiA2OTE1QzZDRUQyNTgxNDNGODkzN0IxMzM1RjQ4ODdG
+MDA0MkI3QzYzMDA1Mzk4RjkzOTZCQjg1MzIzOENCNiMpKSkKNjE1Q0Q1NkZBNTQK
+IEY1QTBCN0VGMjVBMEUyRkU4NDNGQTJFNkUwMjFDQUI0MTE5RTYwMzk0QzlENkEz
+RjdBRDRGNTc3OTZEMzY2NjlBNTEyNjYKIEMyN0E4RDFDNUE2QjQxNDFENUM4MzFF
+ODQ1NDFGM0M4MTFFODkwNzg5ODAzMzgyOTVGODJCN0Y3RkQ0MzMzRUZEOTMzMTIK
+IEYyQUIjKShnICMwNiMpKHkgIzM3NzNBNkQ5RUM4ODlENzZFMzI0RDZFNUVDMjFC
+RDQ1Njk5ODMxQUU0RkQwQUUwMzc4MjAKIDVCQUU1QjhDRTg1RkFEQUJEN0U2QjdD
+NzMwMjVDQjNENzMwRDVDNTgyOTAzNEQ3NkJFMDg1NUMyRTlGRjdBNDkyM0VGRkEK
+IEYxNkE5NjY2OTQ0REJDNjI5NDgzOEZDM0YwOUZGOTY0QThEMDIzQ0I4RUJBMzMy
+RkIwNTFFQTAyODIwRUU2MTIwRkZCRTYKIDJCMzZBMjBwcml2YXRlLWtleXMtdjEu
+ZC8zNDNEOEFGNzk3OTZFRTEwN0Q2NDVBMjc4N0E5RDkyNTJGOTI0RTZGLmtleQAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwMDY0NAAwMDAx
+NzUwADAwMDE3NTAAMDAwMDAwMDA3NTQAMTI3MzY3MjUyNTYAMDIyMDQwACAwAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AHVzdGFyADAwdGV5dGhvb24AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0ZXl0aG9v
+bgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAACgxMTpwcml2YXRlLWtleSgzOmRzYSgxOnAxMjk6AKxx
+qlg9Kz9DZ/3N52BC0w+JtYKke39vpdWVDHR3MHmMJ/31Y2iSpm0fvRs3h1j9/fBV
+mLOZglNQyH62SxdJyZwCelkZzfUy/qLm9Qaqi7wpg0p4EbmWdoFF/A1Zg/MU7D5w
+5xu+EA1J77Z6QyALN9rIOXZ7rLLa64lw/MV4LdIPKSgxOnEyMToAuOPYbSW26ea5
+CR7wQ7OGMRCJJOcpKDE6ZzEyODpfiE8aUjDk+UeuwbuF1qGFO51XmFEaW+iyfCyt
+gle8oBAsBXURXbpIhhQfmkz/Jxesbbl2pWgbnq5CqeEF1SqjiJKezFjdkwDjoPXh
+ERz0//8Ia8n+PZnjWDDy7ygHutLnR2O+hpZvmbKPtuFpxMF19qHdTx1VdwiLVkW+
+2JoYBikoMTp5MTI4OgIF7eNIdpaYiB0427un4ggc26+Y9nkF93DaMnZEaYSeum6g
+/g7D1vwINFgQkMYEWi4DK3W+uH0E/n8o20wS2wvMrbeYaQm5v6ucd001wwFDY6Ad
+wpwP7UCLQcu6qqvwNHdxWYK6+gIsSufLmeMGrsvC0WQqYeu1GfGpHIMCZJlZKSgx
+OngyMDp/2Na42QEhjCvSBm9cv2Qyk9M5EykpKQAAAAAAAAAAAAAAAAAAAAAAAAAA
+cHJpdmF0ZS1rZXlzLXYxLmQvMTNGREI4ODA5QjE3QzU1NDc3NzlGOUQyMDVDNDVG
+NDdDRTAyMTdDRS5rZXkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAADAwMDA2NDQAMDAwMTc1MAAwMDAxNzUwADAwMDAwMDAxNzQyADEyNzM2NzI1
+MjU2ADAyMjAzMgAgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAB1c3RhcgAwMHRleXRob29uAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAdGV5dGhvb24AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABLZXk6IChwcml2YXRlLWtl
+eSAocnNhIChuICMwMEE4NTI1Njc2RUNFNEQ3NUZFNkQwMDczRjJCRjk5QTZGNDkz
+M0NFQkRENAogNTI4QUY1NkU0QzYxRTJGNzMxMjQ3MzkzNjQ1RERBRjU4RUFERDU2
+NTI5QzI1Mzk3NzgyMzY0NjNERjJENDU4NTIwRTgwRQogMzRDMDU4MjQyQjNGRjg4
+REQzOUE4ODNCNDc1QjY2Q0VBQUJCQzk5ODlGRjAxRkZFNzM3NjYwRTlCNjFCQjlE
+QzkxMjA1RAogNDI4RkZGRThGNjc1RkFFRjYxMzY1OEM3MkRBNkQ3NTBDMEVCQzQw
+QUY2MjNEMjA2NjkyQzgyNTE0QzQwNEQ4ODI1QUI3MAogMTAwMSMpKGUgIzAxMDEj
+KShkICMwMEJDQTAwMTQ0ODVGQjc2RDUwRTlCNkNCQTU3MjFBQzExMjEzOTBGODYw
+OEQ0MDg0QgogRDA0NUE4NzZERjM4MTBGMTE0QkMyRDY4RUI1NTJFNjFCMDFFREJD
+MjQ4MUYwOEM4MjgzMkUwMEUyNzlENjdBODUzMDU1RAogQ0FFNUMyMzU2ODUxQ0JF
+MzZENjEwQzREMkFCNDNGQTY1NTk4NUM0NDY5RDFEOTExRTFBRkQ4MTdFQUE1RkVF
+MEZGMjY1NwogNEMzNTlFMTc1Mjg3MDUyMTk0NTNCNTFBRUMxMERCRjc1NjJCMDYx
+RDVDNjZDMzVCQjNGOUYwQjIyMkI5RDE5NkI5IykocAogICMwMEMzM0M1ODA2Mzk5
+NkJENTk3NTJBQUJERkRBQ0RBQTdCNEI2NkFBMTc1NEVFMEQ4OUI3Nzk0RjBERThG
+RjcyNEM1NAogOUZGMTEyQTMzMjkyQkI5RDdCQ0VFNzk0RjA4MDI0QzNFNTVGRDgy
+MzNGNTA3OUVENDk5MUM0REYyNjE4RDkjKShxICMwMAogRENCNTk0NUYwMEYxQUY0
+MzhCRDRDMzExQjhCQUNBM0Q5REIwQUQxNjUxOTg2NTM0MjAzMEYxREYzMDU3RTU1
+MzJDNDdGNQogOEQzMzAzQ0JBM0M4QTI5ODE0RjYxN0I3QjNERUU5OEZBQUFBRUU4
+MTFCNDk4RkFBRjIxNzdCNzc2OSMpKHUgIzI5RkIyRAogRjY5QjIzNUE0OUE5MDZC
+MTBFRjdEOEY4MUFBRUE4QUQ4MUU3Q0RERTFGNEE3OUNFMjQ0QkY4RkNFNkRENUVC
+MTgxMUIwQgogRDVFNTE2NUI5NTcwODUwMzY5MDFERDI4NUE2MjhDMjk3QTc4MkRB
+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
+MDAwMjI2MAAxMjczNjcyNTI1NgAwMTM2MjcAIDAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdXN0YXIAMDB0ZXl0aG9v
+bgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHRleXRob29uAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AWdwZwMDAQUBAgAAVxi2IwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAA==
+=Joz2
+-----END PGP ARMORED FILE-----
diff --git a/tests/migrations/from-classic.scm b/tests/migrations/from-classic.scm
new file mode 100755
index 0000000..b473d70
--- /dev/null
+++ b/tests/migrations/from-classic.scm
@@ -0,0 +1,61 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "migrations" "common.scm"))
+
+(catch (skip "gpgtar not built")
+ (call-check `(,GPGTAR --help)))
+
+(define (trigger-migration)
+ (call-check `(,@GPG --list-secret-keys)))
+
+(define (assert-migrated)
+ (unless (file-exists? ".gpg-v21-migrated")
+ (error "Not migrated"))
+
+ (for-each
+ (lambda (keyid)
+ (catch (error "Key not found:" keyid)
+ (call-check `(,@GPG --list-secret-keys ,keyid))))
+ '("D74C5F22" "C40FDECF" "ECABF51D")))
+
+(run-test
+ "Testing a clean migration ..."
+ (in-srcdir "tests" "migrations" "from-classic.tar.asc")
+ (lambda (gpghome)
+ (trigger-migration)
+ (assert-migrated)))
+
+(run-test
+ "Testing a migration with existing private-keys-v1.d ..."
+ (in-srcdir "tests" "migrations" "from-classic.tar.asc")
+ (lambda (gpghome)
+ (mkdir "private-keys-v1.d" "-rwx")
+ (trigger-migration)
+ (assert-migrated)))
+
+(run-test
+ "Testing a migration with existing but weird private-keys-v1.d ..."
+ (in-srcdir "tests" "migrations" "from-classic.tar.asc")
+ (lambda (gpghome)
+ (mkdir "private-keys-v1.d" "")
+ (trigger-migration)
+ (assert-migrated)))
+
+;; XXX Check a case where the migration fails.
diff --git a/tests/migrations/from-classic.tar.asc b/tests/migrations/from-classic.tar.asc
new file mode 100644
index 0000000..f35637d
--- /dev/null
+++ b/tests/migrations/from-classic.tar.asc
@@ -0,0 +1,209 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+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
+AxUCAwMWAgECHgECF4AACgkQ0SC2Juyr9R1qQwP/bCDX1WGk1u0zkKJWJ/VXnuH3
+jk6ZevkuHZICwjlqAxv1de5P3Jeya/4kPmEQTotEv3xcDAZ+9pBL3TrZolAKhxkB
+Z08l4QSy76kyf8hB0eoZ2Svs7LrGPBJr6CHX0kyDiapHgAhBKQq9GhNKpIAZuL6D
+K2dOaQDtoRSW2iB1h4mwAgAA9gGehrd8xqenTd5nmLxvBiIiLxYmZimDq7eP17AJ
+z4V3rWzdt7zt3Scarg/bMDvKYcEdruoou/PZ214w+rzssr+1nKIFFUExwvaSUKzp
+A1/WjMYlVh7779qNhTlP5yWp8C/0DeCdLC9+srS6KoZ0cnVzdGRiLmdwZwAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwMDY0NAAwMDAx
+NzUwADAwMDE3NTAAMDAwMDAwMDIyNjAAMTI3MzY3MjQ2MTcAMDEzNjI3ACAwAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AHVzdGFyADAwdGV5dGhvb24AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0ZXl0aG9v
+bgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAFncGcDAwEFAQIAAFcXZyEAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAEKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
+=nYpX
+-----END PGP ARMORED FILE-----
diff --git a/tests/migrations/issue2276.scm b/tests/migrations/issue2276.scm
new file mode 100755
index 0000000..8ea3f43
--- /dev/null
+++ b/tests/migrations/issue2276.scm
@@ -0,0 +1,32 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "migrations" "common.scm"))
+
+(run-test
+ "Checking migration with legacy key (issue2276)..."
+ ;; This tarball contains a keyring with a legacy key.
+ (in-srcdir "tests" "migrations" "issue2276.tar.asc")
+ (lambda (gpghome)
+ ;; GnuPG up to 2.1.14 failed to skip the legacy key when updating
+ ;; the trust database and thereby rebuilding the keyring cache.
+ (call-check `(,@GPG-no-batch --check-trustdb))
+
+ ;; Check that the other key is fine.
+ (call-check `(,@GPG --list-keys alpha))))
diff --git a/tests/migrations/issue2276.tar.asc b/tests/migrations/issue2276.tar.asc
new file mode 100644
index 0000000..7890e40
--- /dev/null
+++ b/tests/migrations/issue2276.tar.asc
@@ -0,0 +1,326 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+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
+AAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwNjAwADAwMDE3NTAAMDAwMTc1MAAwMDAw
+MDAwMDAwMAAxMjc0NDQwNjEyMQAwMTM1MzIAIDAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdXN0YXIAMDB0ZXl0aG9v
+bgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHRleXRob29uAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+dHJ1c3RkYi5ncGcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAADAwMDA2MDAAMDAwMTc1MAAwMDAxNzUwADAwMDAwMDAyMjYwADEyNzQ0NDA2
+MTMyADAxMzYwMwAgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAB1c3RhcgAwMHRleXRob29uAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAdGV5dGhvb24AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABZ3BnAwMBBQECAABXkgxa
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+=YNes
+-----END PGP ARMORED FILE-----
diff --git a/tests/migrations/run-tests.scm b/tests/migrations/run-tests.scm
new file mode 100644
index 0000000..f44334c
--- /dev/null
+++ b/tests/migrations/run-tests.scm
@@ -0,0 +1,27 @@
+;; Test-suite runner.
+;;
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(define tests (filter (lambda (arg) (not (string-prefix? arg "--"))) *args*))
+
+(run-tests (if (null? tests)
+ (load-tests "tests" "migrations")
+ (map (lambda (name)
+ (test::scm #f
+ (path-join "tests" "migrations" name)
+ (in-srcdir "tests" "migrations" name))) tests)))
diff --git a/tests/migrations/setup.scm b/tests/migrations/setup.scm
new file mode 100644
index 0000000..76a5840
--- /dev/null
+++ b/tests/migrations/setup.scm
@@ -0,0 +1,20 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+;; Nothing to do for now.
diff --git a/tests/openpgp/4gb-packet.asc b/tests/openpgp/4gb-packet.asc
new file mode 100644
index 0000000..7e5d6f3
--- /dev/null
+++ b/tests/openpgp/4gb-packet.asc
Binary files differ
diff --git a/tests/openpgp/4gb-packet.scm b/tests/openpgp/4gb-packet.scm
new file mode 100755
index 0000000..e1c5ba5
--- /dev/null
+++ b/tests/openpgp/4gb-packet.scm
@@ -0,0 +1,29 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+;; GnuPG through 2.1.7 would incorrect mark packets whose size is
+;; 2^32-1 as invalid and exit with status code 2.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-environment)
+
+(unless (have-compression-algo? "BZIP2")
+ (skip "BZIP2 support not compiled in."))
+
+(call-check `(,@GPG --list-packets ,(in-srcdir "tests" "openpgp" "4gb-packet.asc")))
diff --git a/tests/openpgp/ChangeLog-2011 b/tests/openpgp/ChangeLog-2011
new file mode 100644
index 0000000..4013a08
--- /dev/null
+++ b/tests/openpgp/ChangeLog-2011
@@ -0,0 +1,424 @@
+2011-12-01 Werner Koch <wk@g10code.com>
+
+ NB: ChangeLog files are no longer manually maintained. Starting
+ on December 1st, 2011 we put change information only in the GIT
+ commit log, and generate a top-level ChangeLog file from logs at
+ "make dist". See doc/HACKING for details.
+
+2011-02-10 Werner Koch <wk@g10code.com>
+
+ * ecc.test: New.
+ * pinentry.sh: New.
+ * defs.inc: Do not create a log when running tests with envvar
+ verbose > 1. Add pinentry-program to gpg-agent.conf.
+ * Makefile.am (sample_keys): New.
+ (EXTRA_DIST): Add them.
+
+2010-10-15 Werner Koch <wk@g10code.com>
+
+ * Makefile.am (clean-local): New.
+
+2010-10-14 Werner Koch <wk@g10code.com>
+
+ * genkey1024.test: Use the new no-protection option.
+
+ * decrypt-dsa.test: Do not specify an extra keyring. The keyring
+ has been loaded into pubring.gpg.
+ * sigs-dsa.test: Ditto.
+ * encrypt-dsa.test: Ditto.
+ * signencrypt-dsa.test: Ditto.
+
+ * decrypt.test: Remove passphrase stuff.
+ * sigs.test: Ditto.
+
+ * privkeys/: New.
+
+ * Makefile.am: Move most stuff to ...
+ * version.test: Prepare data files etc.
+ * finish.test: New.
+ * defs.inc: Set all envvars.
+ (usrname1, usrname2, username3): Use full mail address.
+
+2010-06-07 Werner Koch <wk@g10code.com>
+
+ * Makefile.am (TESTS_ENVIRONMENT): New. Start all scripts under
+ the control of the gpg-agent.
+ (prepared.stamp): Create gpg-agent.conf.
+ * defs.inc: Do not create gpg-agent.conf
+ (GNUPGHOME): Check that it is set properly.
+ (GPG_AGENT_INFO): Do not change.
+
+2010-05-12 Werner Koch <wk@g10code.com>
+
+ * armor.test (Version): Add test for bug#1179.
+
+2010-05-11 Werner Koch <wk@g10code.com>
+
+ * genkey1024.test: Use GPG macro.
+
+ * gpg-agent.conf.tmpl: New.
+ * defs.inc: Create gpg-agent.conf
+ (GNUPGHOME): Set and export.
+ (GPG_AGENT_INFO): Unset.
+ * Makefile.am (CLEANFILES): Add S.gpg-agent
+
+2010-05-07 Werner Koch <wk@g10code.com>
+
+ * import.test: Add test case for bug#1223.
+ * bug1223-good.asc, bug1223-bogus.asc: New.
+
+2009-12-21 Werner Koch <wk@g10code.com>
+
+ * Makefile.am (required_pgms): New.
+ (./gpg_dearmor): Depend on them.
+
+2009-06-05 David Shaw <dshaw@jabberwocky.com>
+
+ * defs.inc: Improved all_cipher_algos and all_hash_algos to work
+ when there are more than one line of algorithms. From 1.4.
+
+2009-04-19 Werner Koch <wk@g10code.com>
+
+ * mkdemodirs (GPG): Use --no-options.
+
+2008-09-29 Werner Koch <wk@g10code.com>
+
+ * clearsig.test: Replace -sat by --clearsign.
+
+2008-03-19 Werner Koch <wk@g10code.com>
+
+ * import.test, bug894-test.asc: New.
+
+2007-12-14 Werner Koch <wk@g10code.com>
+
+ * Makefile.am (./gpg_dearmor): Reverted last change because the
+ real fix is to --no-options.
+
+2007-11-22 Werner Koch <wk@g10code.com>
+
+ * Makefile.am (./gpg_dearmor): Add --homedir so that we don't
+ auto create a ~/.gnupg/. From Gentoo.
+
+2007-10-25 Werner Koch <wk@g10code.com>
+
+ Add missing copyright notices to *.test.
+
+2007-10-25 David Shaw <dshaw@jabberwocky.com> (wk)
+
+ From 1.4 (July):
+
+ * defs.inc (all_cipher_algos): New function to return all ciphers.
+ * defs.inc (all_cipher_algos): New function to return all ciphers
+ we support. This is safer than the previous setup which could
+ hide that some ciphers weren't being tested. Plus, this
+ automatically tests any new ciphers libgcrypt supports.
+ (all_hash_algos): New.
+ * sigs.test: Use it here, and also test with >=160 bit hashes for
+ DSA2.
+ * conventional.test, encrypt.test, encrypt-dsa.test,
+ * conventional-mdc.test: Use it here.
+
+2007-05-02 David Shaw <dshaw@jabberwocky.com>
+
+ * conventional.test, encrypt.test, encrypt-dsa.test,
+ conventional-mdc.test: Fix some broken tests that were only
+ testing 3DES instead of all available ciphers.
+
+2007-03-04 David Shaw <dshaw@jabberwocky.com> (wk)
+
+ * verify.test: Use --allow-multiple-messages instead of
+ --allow-multisig-verification. Two clearsigs in a row counds as a
+ multiple-message test.
+
+2006-11-16 Werner Koch <wk@g10code.com>
+
+ * Makefile.am (plain-large): Use gpg.texi instead of FAQ which
+ won't be found as it is not a source file. Pointed out by Moritz.
+
+2006-10-04 Werner Koch <wk@g10code.com>
+
+ * signencrypt.test: Need to prepend srcdir to the file name
+
+2006-09-27 Werner Koch <wk@g10code.com>
+
+ * signencrypt.test: Add a test for bug 537.
+ * bug537-test.data.asc: New. Taken from the BTS.
+
+2006-08-21 Werner Koch <wk@g10code.com>
+
+ Copied tests from 1.4 and adjusted paths.
+
+2006-04-19 David Shaw <dshaw@jabberwocky.com>
+
+ * sigs.test, mds.test: Add tests for SHA-224, SHA-384, and
+ SHA-512.
+
+2006-04-11 Werner Koch <wk@g10code.com>
+
+ * armor.test: New.
+
+2006-03-09 Werner Koch <wk@g10code.com>
+
+ * defs.inc: Removed Basishm by proper redirection.
+
+2006-03-06 Werner Koch <wk@g10code.com>
+
+ * defs.inc: Print error messages also to stderr. Allow for
+ verbose environment variable.
+ (linefeed): New.
+ (suspend_error, resume_error): New.
+ * verify.test: More tests.
+ * multisig.test: Better error printing.
+ (sig_1ls1ls_valid, sig_ls_valid): Moved to the non-valid group.
+
+2006-02-14 Werner Koch <wk@gnupg.org>
+
+ * verify.test: New.
+
+2005-06-21 Werner Koch <wk@g10code.com>
+
+ * conventional.test (algos): Uhh ohh, cut+paste error and not
+ tested.
+
+2005-06-02 Werner Koch <wk@g10code.com>
+
+ * conventional.test: have_cipher_algo now requires uppercase
+ algorithm names. Changed. Noted by John R. Shannon.
+
+2004-02-09 David Shaw <dshaw@jabberwocky.com>
+
+ * clearsig.test, sigs.test: Properly detect RSA being missing, and
+ use the proper key for doing an RSA test.
+
+2003-12-31 David Shaw <dshaw@jabberwocky.com>
+
+ * clearsig.test, conventional-mdc.test, conventional.test,
+ defs.inc, encrypt-dsa.test, encrypt.test, genkey1024.test,
+ plain-1.asc, plain-1-pgp.asc, plain-2.asc, plain-3.asc,
+ pubring.asc, secring.asc, sigs.test: Rework tests to work properly
+ with a gpg binary that doesn't have all ciphers and all pk algos.
+ Basically, we test for the ciphers we have, only test signing with
+ non-160-bit hashes with RSA (we test all hashes as hashes). Test
+ all key lengths of AES.
+
+2003-12-05 David Shaw <dshaw@jabberwocky.com>
+
+ * Makefile.am: Reenable tests now that the Elgamal signature keys
+ are gone.
+
+ * defs.inc, pubring.asc, secring.asc, plain-1.asc, plain-2.asc,
+ plain-3.asc: Remove the old v3 Elgamal keys and replace with
+ RSA+Elgamal and RSA s+e.
+
+2003-12-03 David Shaw <dshaw@jabberwocky.com>
+
+ * options: Remove emulate-md-encode-bug.
+
+2003-11-27 Werner Koch <wk@gnupg.org>
+
+ * Makefile.am (TESTS): Temporary remove tests using ElG signatures.
+
+2003-09-04 David Shaw <dshaw@jabberwocky.com>
+
+ * mds.test, sigs.test: Remove TIGER/192 and make SHA-256 optional
+ (since it might not be compiled in).
+
+2003-07-10 David Shaw <dshaw@jabberwocky.com>
+
+ * Makefile.am: Add --no-permission-warning to avoid spurious
+ warning when importing demo keys.
+
+2003-05-27 Werner Koch <wk@gnupg.org>
+
+ * Makefile.am (CLEANFILES): Add gpg.conf
+
+2003-05-26 David Shaw <dshaw@jabberwocky.com>
+
+ * defs.inc (pgmname): Make sure there is a valid options
+ file. (From wk on stable branch)
+
+ * mds.test: Note that missing algorithms are not errors.
+
+2003-04-23 David Shaw <dshaw@jabberwocky.com>
+
+ * Makefile.am, options.in: Rename options.in to options since it
+ no longer needs to be a generated file.
+
+ * sigs.test: TODO note to add the new SHAs when we start
+ generating them.
+
+ * mds.test: Test the new SHAs.
+
+2002-05-10 Werner Koch <wk@gnupg.org>
+
+ * Makefile.am: Add gpg_dearmor to all targets where it is used.
+ Noted by Andreas Haumer.
+
+2002-04-19 Werner Koch <wk@gnupg.org>
+
+ * signencrypt-dsa.test, sigs-dsa.test: Don't check with MD5 as
+ this is not valid with DSA signatures.
+
+2001-12-22 Werner Koch <wk@gnupg.org>
+
+ * options.in: Add no-permission-warning.
+
+2001-12-21 Werner Koch <wk@gnupg.org>
+
+ * Makefile.am (distclean-local): prefix mkdemodirs with srcdir
+ (DISTCLEANFILES): Add random_seed.
+
+2001-12-19 Werner Koch <wk@gnupg.org>
+
+ * options.in: Remove load-extension tiger
+ * Makefile.am (./options): append it if there is such a module.
+
+2001-10-23 Werner Koch <wk@gnupg.org>
+
+ * defs.inc, Makefile.am: Do not use $srcdir when invoking gpg.
+ Write the logfile to the current directory.
+
+2001-09-28 Werner Koch <wk@gnupg.org>
+
+ * defs.inc: Write a log file for each test.
+ * run-gpg, run-gpgm, run-gpg.patterns: Removed. Replaced in all
+ tests by a simple macro from defs.inc.
+ * Makefile.am (CLEANFILES): Remove log files.
+ (./gpg_dearmor): create it and use it instead of the macro.
+ This is needed in multisig.test due to IFS tricks.
+
+ * armsignencrypt.test, signencrypt-dsa.test, signencrypt.test,
+ armencryptp.test, armencrypt.test, encryptp.test, seat.test,
+ encrypt-dsa.test, encrypt.test: Use --always-trust because the
+ test are not designed to check the validity.
+
+2001-09-06 Werner Koch <wk@gnupg.org>
+
+ * genkey1024.test: Simplified by using a parameter file.
+
+2001-05-30 Werner Koch <wk@gnupg.org>
+
+ * multisig.test (IFS): Reset IFS just before the test.
+
+2001-04-30 Werner Koch <wk@gnupg.org>
+
+ * multisig.test: Add an set +x to avoid ksh problems
+
+2001-04-28 Werner Koch <wk@gnupg.org>
+
+ * run-gpg.patterns: a v3 test key expired yesterday, suppress the
+ messages.
+
+2001-03-27 Werner Koch <wk@gnupg.org>
+
+ * defs.inc: Removed creation of options file.
+ * options.in: New.
+ * Makefile.am: Create options file and fixed import of pubdemo.asc.
+
+ * run-gpg.patterns (gpg): Add some more patterns.
+
+2001-03-20 Werner Koch <wk@gnupg.org>
+
+ * Makefile.am: Import the pubdemo.asc file
+
+ * sigs.test (hash_algo_list): s/tiger/tiger192/
+
+2001-03-19 Werner Koch <wk@gnupg.org>
+
+ * mkdemodirs (GPGDEMO): Add --allow-secret-key-import to all gpg
+ invocations. Use echon -n instead of an argument with \c.
+
+2001-02-12 Werner Koch <wk@gnupg.org>
+
+ * multisig.test: new
+ * Makefile.am (TESTS): Added.
+
+2000-10-18 Werner Koch <wk@gnupg.org>
+
+ * conventional-mdc.test: Add Rijndael and fix for empty plain texts.
+
+Thu Feb 10 17:39:44 CET 2000 Werner Koch <wk@gnupg.de>
+
+ * mkdemodirs: Fixed the --clean loop.
+
+Thu Jan 13 19:31:58 CET 2000 Werner Koch <wk@gnupg.de>
+
+ * defs.inc (chdir): Removed becuase it is unsused an plain old sh
+ does not like this name. Reported by Alec Habig.
+
+Tue Oct 26 20:02:23 1999 Werner Koch (wk@gnupg.org)
+
+ * Makefile.am (GPG_DEARMOR): New and use --no-options.
+
+Tue Aug 31 17:20:44 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
+
+ * defs.inc: set LC_ALL empty
+
+Wed Aug 4 10:34:18 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
+
+ * defs.inc (echo_n): New and used instead of /bin/echo "\c"
+
+Sun Apr 18 10:11:28 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
+
+ * mkdemodirs: New
+ * signdemokey: New.
+ * Makefile.am (distclean-local): New.
+
+Wed Mar 17 13:09:03 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
+
+ * mds.test: replaced the "echo -n"
+
+Mon Mar 8 20:47:17 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
+
+ * pubdemo.asc, secdemo.asc: New.
+
+Fri Feb 19 15:49:15 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
+
+ * genkey1024.test: Be really quiet.
+
+1999-01-01 Geoff Keating <geoffk@ozemail.com.au>
+
+ * Makefile.am (CLEANFILES): Also delete trustdb and any leftover
+ lockfiles.
+
+Fri Nov 27 15:30:24 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
+
+ * clearsig.test: Some more test cases.
+
+Sun Oct 25 18:19:35 1998 Werner Koch (wk@isil.d.shuttle.de)
+
+ * mds.test: Check whether TIGER is available.
+ * sigs.tesr: Ditto.
+
+Wed Sep 23 12:25:07 1998 Werner Koch (wk@isil.d.shuttle.de)
+
+ * run-gpg.patterns: New (because Solaris fgrep does not like -f -).
+
+Mon Aug 10 21:33:38 1998 Werner Koch (wk@(none))
+
+ * genkey1024.test: Ariel fixed this.
+
+Wed Jul 8 10:43:47 1998 Werner Koch (wk@isil.d.shuttle.de)
+
+ * seat.test: New.
+
+Mon May 18 15:40:02 1998 Werner Koch (wk@isil.d.shuttle.de)
+
+ * Makefile.am: Now uses mk-tdata to produce random test data.
+
+ * ChangeLog: New.
+
+
+ Copyright 1998, 1999, 2000, 2001, 2007 Free Software Foundation, Inc.
+
+ This file is free software; as a special exception the author gives
+ unlimited permission to copy and/or distribute it, with or without
+ modifications, as long as this notice is preserved.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+Local Variables:
+buffer-read-only: t
+End:
diff --git a/tests/openpgp/Makefile.am b/tests/openpgp/Makefile.am
new file mode 100644
index 0000000..59f39e2
--- /dev/null
+++ b/tests/openpgp/Makefile.am
@@ -0,0 +1,290 @@
+# Makefile.am - For tests/openpgp
+# Copyright (C) 1998, 1999, 2000, 2001, 2003,
+# 2010 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+# Process this file with automake to create Makefile.in
+
+
+# Programs required before we can run these tests.
+required_pgms = ../../g10/gpg$(EXEEXT) ../../agent/gpg-agent$(EXEEXT) \
+ ../../tools/gpg-connect-agent$(EXEEXT) \
+ ../gpgscm/gpgscm$(EXEEXT)
+
+AM_CPPFLAGS = -I$(top_srcdir)/common
+include $(top_srcdir)/am/cmacros.am
+
+AM_CFLAGS =
+
+noinst_PROGRAMS = fake-pinentry
+
+fake_pinentry_SOURCES = fake-pinentry.c
+
+TESTS_ENVIRONMENT = LC_ALL=C \
+ EXEEXT=$(EXEEXT) \
+ PATH="../gpgscm:$(PATH)" \
+ abs_top_srcdir="$(abs_top_srcdir)" \
+ objdir="$(abs_top_builddir)" \
+ GPGSCM_PATH="$(abs_top_srcdir)/tests/gpgscm"
+
+XTESTS = \
+ version.scm \
+ enarmor.scm \
+ mds.scm \
+ decrypt.scm \
+ decrypt-multifile.scm \
+ decrypt-dsa.scm \
+ decrypt-session-key.scm \
+ decrypt-unwrap-verify.scm \
+ sigs.scm \
+ sigs-dsa.scm \
+ encrypt.scm \
+ encrypt-multifile.scm \
+ encrypt-dsa.scm \
+ compression.scm \
+ seat.scm \
+ clearsig.scm \
+ encryptp.scm \
+ detach.scm \
+ detachm.scm \
+ armsigs.scm \
+ armencrypt.scm \
+ armencryptp.scm \
+ signencrypt.scm \
+ signencrypt-dsa.scm \
+ armsignencrypt.scm \
+ armdetach.scm \
+ armdetachm.scm \
+ genkey1024.scm \
+ conventional.scm \
+ conventional-mdc.scm \
+ multisig.scm \
+ verify.scm \
+ verify-multifile.scm \
+ gpgv.scm \
+ gpgv-forged-keyring.scm \
+ armor.scm \
+ import.scm \
+ import-revocation-certificate.scm \
+ ecc.scm \
+ 4gb-packet.scm \
+ tofu.scm \
+ trust-pgp-1.scm \
+ trust-pgp-2.scm \
+ trust-pgp-3.scm \
+ gpgtar.scm \
+ use-exact-key.scm \
+ default-key.scm \
+ export.scm \
+ ssh-import.scm \
+ ssh-export.scm \
+ quick-key-manipulation.scm \
+ key-selection.scm \
+ delete-keys.scm \
+ gpgconf.scm \
+ issue2015.scm \
+ issue2346.scm \
+ issue2417.scm \
+ issue2419.scm \
+ issue2929.scm \
+ issue2941.scm
+
+# Temporary removed tests:
+# trust-pgp-4.scm
+
+
+# XXX: Currently, one cannot override automake's 'check' target. As a
+# workaround, we avoid defining 'TESTS', thus automake will not emit
+# the 'check' target. For extra robustness, we merely define a
+# dependency on 'xcheck', so this hack should also work even if
+# automake would emit the 'check' target, as adding dependencies to
+# targets is okay.
+check: xcheck
+
+.PHONY: xcheck
+xcheck:
+ $(TESTS_ENVIRONMENT) $(abs_top_builddir)/tests/gpgscm/gpgscm \
+ $(abs_srcdir)/run-tests.scm $(TESTFLAGS) $(TESTS)
+
+TEST_FILES = pubring.asc secring.asc plain-1o.asc plain-2o.asc plain-3o.asc \
+ plain-1.asc plain-2.asc plain-3.asc plain-1-pgp.asc \
+ plain-largeo.asc plain-large.asc \
+ pubring.pkr.asc secring.skr.asc secdemo.asc pubdemo.asc \
+ bug537-test.data.asc bug894-test.asc \
+ bug1223-good.asc bug1223-bogus.asc 4gb-packet.asc \
+ tofu/conflicting/1C005AF3.gpg \
+ tofu/conflicting/1C005AF3-secret.gpg \
+ tofu/conflicting/1C005AF3-1.txt \
+ tofu/conflicting/1C005AF3-2.txt \
+ tofu/conflicting/1C005AF3-3.txt \
+ tofu/conflicting/1C005AF3-4.txt \
+ tofu/conflicting/1C005AF3-5.txt \
+ tofu/conflicting/B662E42F.gpg \
+ tofu/conflicting/B662E42F-secret.gpg \
+ tofu/conflicting/B662E42F-1.txt \
+ tofu/conflicting/B662E42F-2.txt \
+ tofu/conflicting/B662E42F-3.txt \
+ tofu/conflicting/B662E42F-4.txt \
+ tofu/conflicting/B662E42F-5.txt \
+ tofu/conflicting/BE04EB2B.gpg \
+ tofu/conflicting/BE04EB2B-secret.gpg \
+ tofu/conflicting/BE04EB2B-1.txt \
+ tofu/conflicting/BE04EB2B-2.txt \
+ tofu/conflicting/BE04EB2B-3.txt \
+ tofu/conflicting/BE04EB2B-4.txt \
+ tofu/conflicting/BE04EB2B-5.txt \
+ tofu/cross-sigs/EC38277E-secret.gpg \
+ tofu/cross-sigs/EC38277E-1.gpg \
+ tofu/cross-sigs/EC38277E-1.txt \
+ tofu/cross-sigs/EC38277E-2.gpg \
+ tofu/cross-sigs/EC38277E-2.txt \
+ tofu/cross-sigs/EC38277E-3.txt \
+ tofu/cross-sigs/871C2247-secret.gpg \
+ tofu/cross-sigs/871C2247-1.gpg \
+ tofu/cross-sigs/871C2247-1.txt \
+ tofu/cross-sigs/871C2247-2.gpg \
+ tofu/cross-sigs/871C2247-2.txt \
+ tofu/cross-sigs/871C2247-3.gpg \
+ tofu/cross-sigs/871C2247-3.txt \
+ tofu/cross-sigs/871C2247-4.gpg \
+ tofu/cross-sigs/README \
+ key-selection/0.asc \
+ key-selection/1.asc \
+ key-selection/2.asc \
+ key-selection/3.asc \
+ key-selection/4.asc \
+ trust-pgp/scenario1.asc \
+ trust-pgp/scenario2.asc \
+ trust-pgp/scenario3.asc \
+ trust-pgp/scenario4.asc \
+ trust-pgp/alice.sec.asc \
+ trust-pgp/bobby.sec.asc \
+ trust-pgp/carol.sec.asc \
+ trust-pgp/david.sec.asc \
+ trust-pgp/frank.sec.asc \
+ trust-pgp/grace.sec.asc \
+ trust-pgp/heidi.sec.asc
+
+data_files = data-500 data-9000 data-32000 data-80000 plain-large
+
+priv_keys = privkeys/50B2D4FA4122C212611048BC5FC31BD44393626E.asc \
+ privkeys/7E201E28B6FEB2927B321F443205F4724EBE637E.asc \
+ privkeys/13FDB8809B17C5547779F9D205C45F47CE0217CE.asc \
+ privkeys/343D8AF79796EE107D645A2787A9D9252F924E6F.asc \
+ privkeys/8B5ABF3EF9EB8D96B91A0B8C2C4401C91C834C34.asc \
+ privkeys/0D6F6AD4C4C803B25470F9104E9F4E6A4CA64255.asc \
+ privkeys/FD692BD59D6640A84C8422573D469F84F3B98E53.asc \
+ privkeys/76F7E2B35832976B50A27A282D9B87E44577EB66.asc \
+ privkeys/A0747D5F9425E6664F4FFBEED20FBCA79FDED2BD.asc \
+ privkeys/0DD40284FF992CD24DC4AAC367037E066FCEE26A.asc \
+ privkeys/2BC997C0B8691D41D29A4EC81CCBCF08454E4961.asc \
+ privkeys/3C9D5ECA70130C2DBB1FC6AC0076BEEEC197716F.asc \
+ privkeys/449E644892C951A37525654730DD32C202079926.asc \
+ privkeys/58FFE844087634E62440224908BDE44BEA7EB730.asc \
+ privkeys/4DF9172D6FF428C97A0E9AA96F03E8BCE3B2F188.asc \
+ privkeys/9D7CD8F53F2F14C3E2177D1E9D1D11F39513A4A4.asc \
+ privkeys/6E6B7ED0BD4425018FFC54F3921D5467A3AE00EB.asc \
+ privkeys/C905D0AB6AE9655C5A35975939997BBF3325D6DD.asc \
+ privkeys/B2BAA7144303DF19BB6FDE23781DD3FDD97918D4.asc \
+ privkeys/CF60965BF51F67CF80DECE853E0D2D343468571D.asc \
+ privkeys/DF00E361D34F80868D06879AC21D7A7D4E4FAD76.asc \
+ privkeys/00FE67F28A52A8AA08FFAED20AF832DA916D1985.asc \
+ privkeys/1DF48228FEFF3EC2481B106E0ACA8C465C662CC5.asc \
+ privkeys/A2832820DC9F40751BDCD375BB0945BA33EC6B4C.asc \
+ privkeys/ADE710D74409777B7729A7653373D820F67892E0.asc \
+ privkeys/CEFC51AF91F68A2904FBFF62C4F075A4785B803F.asc \
+ privkeys/1E28F20E41B54C2D1234D896096495FF57E08D18.asc \
+ privkeys/EB33B687EB8581AB64D04852A54453E85F3DF62D.asc \
+ privkeys/C6A6390E9388CDBAD71EAEA698233FE5E04F001E.asc \
+ privkeys/D69102E0F5AC6B6DB8E4D16DA8E18CF46D88CAE3.asc
+
+sample_keys = samplekeys/README \
+ samplekeys/ecc-sample-1-pub.asc \
+ samplekeys/ecc-sample-2-pub.asc \
+ samplekeys/ecc-sample-3-pub.asc \
+ samplekeys/ecc-sample-1-sec.asc \
+ samplekeys/ecc-sample-2-sec.asc \
+ samplekeys/ecc-sample-3-sec.asc \
+ samplekeys/eddsa-sample-1-pub.asc \
+ samplekeys/eddsa-sample-1-sec.asc \
+ samplekeys/dda252ebb8ebe1af-1.asc \
+ samplekeys/dda252ebb8ebe1af-2.asc \
+ samplekeys/whats-new-in-2.1.asc \
+ samplekeys/e2e-p256-1-clr.asc \
+ samplekeys/e2e-p256-1-prt.asc \
+ samplekeys/E657FB607BB4F21C90BB6651BC067AF28BC90111.asc \
+ samplekeys/rsa-rsa-sample-1.asc \
+ samplekeys/ed25519-cv25519-sample-1.asc \
+ samplekeys/silent-running.asc \
+ samplekeys/ssh-dsa.key \
+ samplekeys/ssh-ecdsa.key \
+ samplekeys/ssh-ed25519.key \
+ samplekeys/ssh-rsa.key \
+ samplekeys/issue2346.gpg \
+ samplekeys/authenticate-only.pub.asc \
+ samplekeys/authenticate-only.sec.asc
+
+sample_msgs = samplemsgs/clearsig-1-key-1.asc \
+ samplemsgs/clearsig-2-keys-1.asc \
+ samplemsgs/clearsig-2-keys-2.asc \
+ samplemsgs/enc-1-key-1.asc \
+ samplemsgs/enc-1-key-2.asc \
+ samplemsgs/enc-2-keys-1.asc \
+ samplemsgs/enc-2-keys-2.asc \
+ samplemsgs/enc-2-keys-hh-1.asc \
+ samplemsgs/enc-2-keys-hr-1.asc \
+ samplemsgs/enc-2-keys-rh-1.asc \
+ samplemsgs/encsig-2-2-keys-3.asc \
+ samplemsgs/encsig-2-2-keys-4.asc \
+ samplemsgs/encsig-2-keys-1.asc \
+ samplemsgs/encsig-2-keys-2.asc \
+ samplemsgs/encsig-2-keys-3.asc \
+ samplemsgs/encsig-2-keys-4.asc \
+ samplemsgs/encz0-1-key-1.asc \
+ samplemsgs/encz0-1-key-2.asc \
+ samplemsgs/issue2419.asc \
+ samplemsgs/revoke-2D727CC768697734.asc \
+ samplemsgs/sig-1-key-1.asc \
+ samplemsgs/sig-1-key-2.asc \
+ samplemsgs/sig-2-keys-1.asc \
+ samplemsgs/sig-2-keys-2.asc \
+ samplemsgs/signed-1-key-1.asc \
+ samplemsgs/signed-1-key-2.asc \
+ samplemsgs/signed-2-keys-1.asc \
+ samplemsgs/signed-2-keys-2.asc
+
+EXTRA_DIST = defs.scm trust-pgp/common.scm $(XTESTS) $(TEST_FILES) \
+ mkdemodirs signdemokey $(priv_keys) $(sample_keys) \
+ $(sample_msgs) ChangeLog-2011 run-tests.scm trust-pgp-4.scm \
+ setup.scm shell.scm all-tests.scm signed-messages.scm
+
+CLEANFILES = prepared.stamp x y yy z out err $(data_files) \
+ plain-1 plain-2 plain-3 trustdb.gpg *.lock .\#lk* \
+ *.log gpg_dearmor gpg.conf gpg-agent.conf S.gpg-agent \
+ pubring.gpg pubring.gpg~ pubring.kbx pubring.kbx~ \
+ secring.gpg pubring.pkr secring.skr \
+ gnupg-test.stop random_seed gpg-agent.log tofu.db \
+ passphrases sshcontrol S.gpg-agent.ssh report.xml
+
+XTESTS += trust-pgp-4.scm
+
+clean-local:
+ -rm -rf private-keys-v1.d openpgp-revocs.d tofu.d gpgtar.d
+
+
+# We need to depend on a couple of programs so that the tests don't
+# start before all programs are built.
+all-local: $(required_pgms)
diff --git a/tests/openpgp/Makefile.in b/tests/openpgp/Makefile.in
new file mode 100644
index 0000000..a911259
--- /dev/null
+++ b/tests/openpgp/Makefile.in
@@ -0,0 +1,940 @@
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am - For tests/openpgp
+# Copyright (C) 1998, 1999, 2000, 2001, 2003,
+# 2010 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+# Process this file with automake to create Makefile.in
+
+# cmacros.am - C macro definitions
+# Copyright (C) 2004 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@HAVE_DOSISH_SYSTEM_FALSE@am__append_1 = -DGNUPG_BINDIR="\"$(bindir)\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_LIBEXECDIR="\"$(libexecdir)\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_LIBDIR="\"$(libdir)/@PACKAGE@\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_DATADIR="\"$(datadir)/@PACKAGE@\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_SYSCONFDIR="\"$(sysconfdir)/@PACKAGE@\"" \
+@HAVE_DOSISH_SYSTEM_FALSE@ -DGNUPG_LOCALSTATEDIR="\"$(localstatedir)\""
+
+
+# If a specific protect tool program has been defined, pass its name
+# to cc. Note that these macros should not be used directly but via
+# the gnupg_module_name function.
+@GNUPG_AGENT_PGM_TRUE@am__append_2 = -DGNUPG_DEFAULT_AGENT="\"@GNUPG_AGENT_PGM@\""
+@GNUPG_PINENTRY_PGM_TRUE@am__append_3 = -DGNUPG_DEFAULT_PINENTRY="\"@GNUPG_PINENTRY_PGM@\""
+@GNUPG_SCDAEMON_PGM_TRUE@am__append_4 = -DGNUPG_DEFAULT_SCDAEMON="\"@GNUPG_SCDAEMON_PGM@\""
+@GNUPG_DIRMNGR_PGM_TRUE@am__append_5 = -DGNUPG_DEFAULT_DIRMNGR="\"@GNUPG_DIRMNGR_PGM@\""
+@GNUPG_PROTECT_TOOL_PGM_TRUE@am__append_6 = -DGNUPG_DEFAULT_PROTECT_TOOL="\"@GNUPG_PROTECT_TOOL_PGM@\""
+@GNUPG_DIRMNGR_LDAP_PGM_TRUE@am__append_7 = -DGNUPG_DEFAULT_DIRMNGR_LDAP="\"@GNUPG_DIRMNGR_LDAP_PGM@\""
+noinst_PROGRAMS = fake-pinentry$(EXEEXT)
+subdir = tests/openpgp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/autobuild.m4 \
+ $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/ksba.m4 \
+ $(top_srcdir)/m4/lcmessage.m4 $(top_srcdir)/m4/ldap.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libassuan.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/npth.m4 $(top_srcdir)/m4/ntbtls.m4 \
+ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \
+ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/readline.m4 \
+ $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \
+ $(top_srcdir)/m4/tar-ustar.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+PROGRAMS = $(noinst_PROGRAMS)
+am_fake_pinentry_OBJECTS = fake-pinentry.$(OBJEXT)
+fake_pinentry_OBJECTS = $(am_fake_pinentry_OBJECTS)
+fake_pinentry_LDADD = $(LDADD)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/fake-pinentry.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(fake_pinentry_SOURCES)
+DIST_SOURCES = $(fake_pinentry_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/am/cmacros.am \
+ $(top_srcdir)/build-aux/depcomp \
+ $(top_srcdir)/build-aux/mkinstalldirs README
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+AWK_HEX_NUMBER_OPTION = @AWK_HEX_NUMBER_OPTION@
+BUILD_FILEVERSION = @BUILD_FILEVERSION@
+BUILD_HOSTNAME = @BUILD_HOSTNAME@
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+BUILD_REVISION = @BUILD_REVISION@
+BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
+BUILD_VERSION = @BUILD_VERSION@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DL_LIBS = @DL_LIBS@
+DNSLIBS = @DNSLIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENCFS = @ENCFS@
+EXEEXT = @EXEEXT@
+FUSERMOUNT = @FUSERMOUNT@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNUPG_AGENT_PGM = @GNUPG_AGENT_PGM@
+GNUPG_DIRMNGR_LDAP_PGM = @GNUPG_DIRMNGR_LDAP_PGM@
+GNUPG_DIRMNGR_PGM = @GNUPG_DIRMNGR_PGM@
+GNUPG_PINENTRY_PGM = @GNUPG_PINENTRY_PGM@
+GNUPG_PROTECT_TOOL_PGM = @GNUPG_PROTECT_TOOL_PGM@
+GNUPG_SCDAEMON_PGM = @GNUPG_SCDAEMON_PGM@
+GPGKEYS_LDAP = @GPGKEYS_LDAP@
+GPGRT_CONFIG = @GPGRT_CONFIG@
+GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
+GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
+GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
+GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
+GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+KSBA_CFLAGS = @KSBA_CFLAGS@
+KSBA_CONFIG = @KSBA_CONFIG@
+KSBA_LIBS = @KSBA_LIBS@
+LBER_LIBS = @LBER_LIBS@
+LDAPLIBS = @LDAPLIBS@
+LDAP_CPPFLAGS = @LDAP_CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
+LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
+LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@
+LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBREADLINE = @LIBREADLINE@
+LIBS = @LIBS@
+LIBUSB_CPPFLAGS = @LIBUSB_CPPFLAGS@
+LIBUSB_LIBS = @LIBUSB_LIBS@
+LIBUTIL_LIBS = @LIBUTIL_LIBS@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NETLIBS = @NETLIBS@
+NPTH_CFLAGS = @NPTH_CFLAGS@
+NPTH_CONFIG = @NPTH_CONFIG@
+NPTH_LIBS = @NPTH_LIBS@
+NTBTLS_CFLAGS = @NTBTLS_CFLAGS@
+NTBTLS_CONFIG = @NTBTLS_CONFIG@
+NTBTLS_LIBS = @NTBTLS_LIBS@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_GT = @PACKAGE_GT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SENDMAIL = @SENDMAIL@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHRED = @SHRED@
+SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
+SQLITE3_LIBS = @SQLITE3_LIBS@
+STRIP = @STRIP@
+SYSROOT = @SYSROOT@
+SYS_SOCKET_H = @SYS_SOCKET_H@
+TAR = @TAR@
+USE_C99_CFLAGS = @USE_C99_CFLAGS@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+W32SOCKLIBS = @W32SOCKLIBS@
+WINDRES = @WINDRES@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+YAT2M = @YAT2M@
+ZLIBS = @ZLIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = $(datadir)/locale
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# Programs required before we can run these tests.
+required_pgms = ../../g10/gpg$(EXEEXT) ../../agent/gpg-agent$(EXEEXT) \
+ ../../tools/gpg-connect-agent$(EXEEXT) \
+ ../gpgscm/gpgscm$(EXEEXT)
+
+
+# NB: AM_CFLAGS may also be used by tools running on the build
+# platform to create source files.
+AM_CPPFLAGS = -I$(top_srcdir)/common -DLOCALEDIR=\"$(localedir)\" \
+ $(am__append_1) $(am__append_2) $(am__append_3) \
+ $(am__append_4) $(am__append_5) $(am__append_6) \
+ $(am__append_7)
+@HAVE_W32CE_SYSTEM_FALSE@extra_sys_libs =
+
+# Under Windows we use LockFileEx. WindowsCE provides this only on
+# the WindowsMobile 6 platform and thus we need to use the coredll6
+# import library. We also want to use a stacksize of 256k instead of
+# the 2MB which is the default with cegcc. 256k is the largest stack
+# we use with pth.
+@HAVE_W32CE_SYSTEM_TRUE@extra_sys_libs = -lcoredll6
+@HAVE_W32CE_SYSTEM_FALSE@extra_bin_ldflags =
+@HAVE_W32CE_SYSTEM_TRUE@extra_bin_ldflags = -Wl,--stack=0x40000
+resource_objs =
+
+# Convenience macros
+libcommon = ../common/libcommon.a
+libcommonpth = ../common/libcommonpth.a
+libcommontls = ../common/libcommontls.a
+libcommontlsnpth = ../common/libcommontlsnpth.a
+AM_CFLAGS =
+fake_pinentry_SOURCES = fake-pinentry.c
+TESTS_ENVIRONMENT = LC_ALL=C \
+ EXEEXT=$(EXEEXT) \
+ PATH="../gpgscm:$(PATH)" \
+ abs_top_srcdir="$(abs_top_srcdir)" \
+ objdir="$(abs_top_builddir)" \
+ GPGSCM_PATH="$(abs_top_srcdir)/tests/gpgscm"
+
+XTESTS = version.scm enarmor.scm mds.scm decrypt.scm \
+ decrypt-multifile.scm decrypt-dsa.scm decrypt-session-key.scm \
+ decrypt-unwrap-verify.scm sigs.scm sigs-dsa.scm encrypt.scm \
+ encrypt-multifile.scm encrypt-dsa.scm compression.scm seat.scm \
+ clearsig.scm encryptp.scm detach.scm detachm.scm armsigs.scm \
+ armencrypt.scm armencryptp.scm signencrypt.scm \
+ signencrypt-dsa.scm armsignencrypt.scm armdetach.scm \
+ armdetachm.scm genkey1024.scm conventional.scm \
+ conventional-mdc.scm multisig.scm verify.scm \
+ verify-multifile.scm gpgv.scm gpgv-forged-keyring.scm \
+ armor.scm import.scm import-revocation-certificate.scm ecc.scm \
+ 4gb-packet.scm tofu.scm trust-pgp-1.scm trust-pgp-2.scm \
+ trust-pgp-3.scm gpgtar.scm use-exact-key.scm default-key.scm \
+ export.scm ssh-import.scm ssh-export.scm \
+ quick-key-manipulation.scm key-selection.scm delete-keys.scm \
+ gpgconf.scm issue2015.scm issue2346.scm issue2417.scm \
+ issue2419.scm issue2929.scm issue2941.scm trust-pgp-4.scm
+TEST_FILES = pubring.asc secring.asc plain-1o.asc plain-2o.asc plain-3o.asc \
+ plain-1.asc plain-2.asc plain-3.asc plain-1-pgp.asc \
+ plain-largeo.asc plain-large.asc \
+ pubring.pkr.asc secring.skr.asc secdemo.asc pubdemo.asc \
+ bug537-test.data.asc bug894-test.asc \
+ bug1223-good.asc bug1223-bogus.asc 4gb-packet.asc \
+ tofu/conflicting/1C005AF3.gpg \
+ tofu/conflicting/1C005AF3-secret.gpg \
+ tofu/conflicting/1C005AF3-1.txt \
+ tofu/conflicting/1C005AF3-2.txt \
+ tofu/conflicting/1C005AF3-3.txt \
+ tofu/conflicting/1C005AF3-4.txt \
+ tofu/conflicting/1C005AF3-5.txt \
+ tofu/conflicting/B662E42F.gpg \
+ tofu/conflicting/B662E42F-secret.gpg \
+ tofu/conflicting/B662E42F-1.txt \
+ tofu/conflicting/B662E42F-2.txt \
+ tofu/conflicting/B662E42F-3.txt \
+ tofu/conflicting/B662E42F-4.txt \
+ tofu/conflicting/B662E42F-5.txt \
+ tofu/conflicting/BE04EB2B.gpg \
+ tofu/conflicting/BE04EB2B-secret.gpg \
+ tofu/conflicting/BE04EB2B-1.txt \
+ tofu/conflicting/BE04EB2B-2.txt \
+ tofu/conflicting/BE04EB2B-3.txt \
+ tofu/conflicting/BE04EB2B-4.txt \
+ tofu/conflicting/BE04EB2B-5.txt \
+ tofu/cross-sigs/EC38277E-secret.gpg \
+ tofu/cross-sigs/EC38277E-1.gpg \
+ tofu/cross-sigs/EC38277E-1.txt \
+ tofu/cross-sigs/EC38277E-2.gpg \
+ tofu/cross-sigs/EC38277E-2.txt \
+ tofu/cross-sigs/EC38277E-3.txt \
+ tofu/cross-sigs/871C2247-secret.gpg \
+ tofu/cross-sigs/871C2247-1.gpg \
+ tofu/cross-sigs/871C2247-1.txt \
+ tofu/cross-sigs/871C2247-2.gpg \
+ tofu/cross-sigs/871C2247-2.txt \
+ tofu/cross-sigs/871C2247-3.gpg \
+ tofu/cross-sigs/871C2247-3.txt \
+ tofu/cross-sigs/871C2247-4.gpg \
+ tofu/cross-sigs/README \
+ key-selection/0.asc \
+ key-selection/1.asc \
+ key-selection/2.asc \
+ key-selection/3.asc \
+ key-selection/4.asc \
+ trust-pgp/scenario1.asc \
+ trust-pgp/scenario2.asc \
+ trust-pgp/scenario3.asc \
+ trust-pgp/scenario4.asc \
+ trust-pgp/alice.sec.asc \
+ trust-pgp/bobby.sec.asc \
+ trust-pgp/carol.sec.asc \
+ trust-pgp/david.sec.asc \
+ trust-pgp/frank.sec.asc \
+ trust-pgp/grace.sec.asc \
+ trust-pgp/heidi.sec.asc
+
+data_files = data-500 data-9000 data-32000 data-80000 plain-large
+priv_keys = privkeys/50B2D4FA4122C212611048BC5FC31BD44393626E.asc \
+ privkeys/7E201E28B6FEB2927B321F443205F4724EBE637E.asc \
+ privkeys/13FDB8809B17C5547779F9D205C45F47CE0217CE.asc \
+ privkeys/343D8AF79796EE107D645A2787A9D9252F924E6F.asc \
+ privkeys/8B5ABF3EF9EB8D96B91A0B8C2C4401C91C834C34.asc \
+ privkeys/0D6F6AD4C4C803B25470F9104E9F4E6A4CA64255.asc \
+ privkeys/FD692BD59D6640A84C8422573D469F84F3B98E53.asc \
+ privkeys/76F7E2B35832976B50A27A282D9B87E44577EB66.asc \
+ privkeys/A0747D5F9425E6664F4FFBEED20FBCA79FDED2BD.asc \
+ privkeys/0DD40284FF992CD24DC4AAC367037E066FCEE26A.asc \
+ privkeys/2BC997C0B8691D41D29A4EC81CCBCF08454E4961.asc \
+ privkeys/3C9D5ECA70130C2DBB1FC6AC0076BEEEC197716F.asc \
+ privkeys/449E644892C951A37525654730DD32C202079926.asc \
+ privkeys/58FFE844087634E62440224908BDE44BEA7EB730.asc \
+ privkeys/4DF9172D6FF428C97A0E9AA96F03E8BCE3B2F188.asc \
+ privkeys/9D7CD8F53F2F14C3E2177D1E9D1D11F39513A4A4.asc \
+ privkeys/6E6B7ED0BD4425018FFC54F3921D5467A3AE00EB.asc \
+ privkeys/C905D0AB6AE9655C5A35975939997BBF3325D6DD.asc \
+ privkeys/B2BAA7144303DF19BB6FDE23781DD3FDD97918D4.asc \
+ privkeys/CF60965BF51F67CF80DECE853E0D2D343468571D.asc \
+ privkeys/DF00E361D34F80868D06879AC21D7A7D4E4FAD76.asc \
+ privkeys/00FE67F28A52A8AA08FFAED20AF832DA916D1985.asc \
+ privkeys/1DF48228FEFF3EC2481B106E0ACA8C465C662CC5.asc \
+ privkeys/A2832820DC9F40751BDCD375BB0945BA33EC6B4C.asc \
+ privkeys/ADE710D74409777B7729A7653373D820F67892E0.asc \
+ privkeys/CEFC51AF91F68A2904FBFF62C4F075A4785B803F.asc \
+ privkeys/1E28F20E41B54C2D1234D896096495FF57E08D18.asc \
+ privkeys/EB33B687EB8581AB64D04852A54453E85F3DF62D.asc \
+ privkeys/C6A6390E9388CDBAD71EAEA698233FE5E04F001E.asc \
+ privkeys/D69102E0F5AC6B6DB8E4D16DA8E18CF46D88CAE3.asc
+
+sample_keys = samplekeys/README \
+ samplekeys/ecc-sample-1-pub.asc \
+ samplekeys/ecc-sample-2-pub.asc \
+ samplekeys/ecc-sample-3-pub.asc \
+ samplekeys/ecc-sample-1-sec.asc \
+ samplekeys/ecc-sample-2-sec.asc \
+ samplekeys/ecc-sample-3-sec.asc \
+ samplekeys/eddsa-sample-1-pub.asc \
+ samplekeys/eddsa-sample-1-sec.asc \
+ samplekeys/dda252ebb8ebe1af-1.asc \
+ samplekeys/dda252ebb8ebe1af-2.asc \
+ samplekeys/whats-new-in-2.1.asc \
+ samplekeys/e2e-p256-1-clr.asc \
+ samplekeys/e2e-p256-1-prt.asc \
+ samplekeys/E657FB607BB4F21C90BB6651BC067AF28BC90111.asc \
+ samplekeys/rsa-rsa-sample-1.asc \
+ samplekeys/ed25519-cv25519-sample-1.asc \
+ samplekeys/silent-running.asc \
+ samplekeys/ssh-dsa.key \
+ samplekeys/ssh-ecdsa.key \
+ samplekeys/ssh-ed25519.key \
+ samplekeys/ssh-rsa.key \
+ samplekeys/issue2346.gpg \
+ samplekeys/authenticate-only.pub.asc \
+ samplekeys/authenticate-only.sec.asc
+
+sample_msgs = samplemsgs/clearsig-1-key-1.asc \
+ samplemsgs/clearsig-2-keys-1.asc \
+ samplemsgs/clearsig-2-keys-2.asc \
+ samplemsgs/enc-1-key-1.asc \
+ samplemsgs/enc-1-key-2.asc \
+ samplemsgs/enc-2-keys-1.asc \
+ samplemsgs/enc-2-keys-2.asc \
+ samplemsgs/enc-2-keys-hh-1.asc \
+ samplemsgs/enc-2-keys-hr-1.asc \
+ samplemsgs/enc-2-keys-rh-1.asc \
+ samplemsgs/encsig-2-2-keys-3.asc \
+ samplemsgs/encsig-2-2-keys-4.asc \
+ samplemsgs/encsig-2-keys-1.asc \
+ samplemsgs/encsig-2-keys-2.asc \
+ samplemsgs/encsig-2-keys-3.asc \
+ samplemsgs/encsig-2-keys-4.asc \
+ samplemsgs/encz0-1-key-1.asc \
+ samplemsgs/encz0-1-key-2.asc \
+ samplemsgs/issue2419.asc \
+ samplemsgs/revoke-2D727CC768697734.asc \
+ samplemsgs/sig-1-key-1.asc \
+ samplemsgs/sig-1-key-2.asc \
+ samplemsgs/sig-2-keys-1.asc \
+ samplemsgs/sig-2-keys-2.asc \
+ samplemsgs/signed-1-key-1.asc \
+ samplemsgs/signed-1-key-2.asc \
+ samplemsgs/signed-2-keys-1.asc \
+ samplemsgs/signed-2-keys-2.asc
+
+EXTRA_DIST = defs.scm trust-pgp/common.scm $(XTESTS) $(TEST_FILES) \
+ mkdemodirs signdemokey $(priv_keys) $(sample_keys) \
+ $(sample_msgs) ChangeLog-2011 run-tests.scm trust-pgp-4.scm \
+ setup.scm shell.scm all-tests.scm signed-messages.scm
+
+CLEANFILES = prepared.stamp x y yy z out err $(data_files) \
+ plain-1 plain-2 plain-3 trustdb.gpg *.lock .\#lk* \
+ *.log gpg_dearmor gpg.conf gpg-agent.conf S.gpg-agent \
+ pubring.gpg pubring.gpg~ pubring.kbx pubring.kbx~ \
+ secring.gpg pubring.pkr secring.skr \
+ gnupg-test.stop random_seed gpg-agent.log tofu.db \
+ passphrases sshcontrol S.gpg-agent.ssh report.xml
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj .rc
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/am/cmacros.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/openpgp/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu tests/openpgp/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/am/cmacros.am $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+
+fake-pinentry$(EXEEXT): $(fake_pinentry_OBJECTS) $(fake_pinentry_DEPENDENCIES) $(EXTRA_fake_pinentry_DEPENDENCIES)
+ @rm -f fake-pinentry$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(fake_pinentry_OBJECTS) $(fake_pinentry_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake-pinentry.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) all-local
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-local clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/fake-pinentry.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/fake-pinentry.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am all-local am--depfiles check \
+ check-am clean clean-generic clean-local clean-noinstPROGRAMS \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am
+
+.PRECIOUS: Makefile
+
+
+@HAVE_W32_SYSTEM_TRUE@.rc.o:
+@HAVE_W32_SYSTEM_TRUE@ $(WINDRES) $(DEFAULT_INCLUDES) $(INCLUDES) "$<" "$@"
+
+# Temporary removed tests:
+# trust-pgp-4.scm
+
+# XXX: Currently, one cannot override automake's 'check' target. As a
+# workaround, we avoid defining 'TESTS', thus automake will not emit
+# the 'check' target. For extra robustness, we merely define a
+# dependency on 'xcheck', so this hack should also work even if
+# automake would emit the 'check' target, as adding dependencies to
+# targets is okay.
+check: xcheck
+
+.PHONY: xcheck
+xcheck:
+ $(TESTS_ENVIRONMENT) $(abs_top_builddir)/tests/gpgscm/gpgscm \
+ $(abs_srcdir)/run-tests.scm $(TESTFLAGS) $(TESTS)
+
+clean-local:
+ -rm -rf private-keys-v1.d openpgp-revocs.d tofu.d gpgtar.d
+
+# We need to depend on a couple of programs so that the tests don't
+# start before all programs are built.
+all-local: $(required_pgms)
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tests/openpgp/README b/tests/openpgp/README
new file mode 100644
index 0000000..22b7211
--- /dev/null
+++ b/tests/openpgp/README
@@ -0,0 +1,257 @@
+# Emacs, this is an -*- org -*- file.
+
+* How to run the test suite
+** tldr: How to run all tests fast.
+
+ obj $ make check-all TESTFLAGS=--parallel
+
+You can use --parallel=N to request N parallel jobs. Hint: Tuck
+TESTFLAGS=--parallel in your environment.
+
+** Running individual test suites or tests
+
+From your build directory, run
+
+ obj $ make -C tests/openpgp check
+
+to run all tests or
+
+ obj $ make -C tests/openpgp check TESTS=your-test.scm
+
+to run a specific test (or any number of tests separated by spaces).
+
+If you want to debug a test, add verbose=1 to see messages printed by
+spawned programs to their standard error stream, verbose=2 to see what
+programs are executed, or verbose=3 to see even more program output
+and exit codes.
+
+If you want to run gpg under valgrind add with_valgrind=1.
+
+
+** Inspecting the test environment
+
+To inspect the environment in which tests are running, or to quickly
+create keys for debugging or testing, you can start a shell. There is
+one test that doese just that:
+
+ obj $ make -C tests/openpgp check TESTS=shell.scm
+ PASS: tests/openpgp/setup.scm
+ Load legacy test environment? [Y/n] y
+ Drop 'batch' from gpg.conf? [Y/n] y
+
+ Enjoy your test environment. Type 'exit' to exit it, it will be cleaned up after you.
+
+ ... $ gpg -k Alfa
+ gpg: NOTE: THIS IS A DEVELOPMENT VERSION!
+ gpg: It is only intended for test purposes and should NOT be
+ gpg: used in a production environment or with production keys!
+ gpg: /tmp/gpgscm-20170809T144032-run-tests-PFfybw/trustdb.gpg: trustdb created
+ pub dsa1024 1999-03-08 [SCA]
+ A0FF4590BB6122EDEF6E3C542D727CC768697734
+ uid [ unknown] Alfa Test (demo key) <alfa@example.net>
+ uid [ unknown] Alpha Test (demo key) <alpha@example.net>
+ uid [ unknown] Alice (demo key)
+ sub elg1024 1999-03-08 [E]
+
+PATH is adjusted so that you will use the tools from the build tree.
+Note that the directory is removed when you exit the shell.
+
+** Passing options to the test driver
+
+You can set TESTFLAGS to pass flags to 'run-tests.scm'. For example,
+to speed up the test suite when bisecting, do
+
+ obj $ make -C tests/openpgp check TESTFLAGS=--parallel
+
+See below for the arguments supported by the driver.
+
+** Calling the test driver directly
+This is a bit tricky because one needs to manually set some
+environment variables. We should make that easier. See discussion
+below. From your build directory, do:
+
+ obj $ srcdir=<path to>/tests/openpgp \
+ GPGSCM_PATH=<path to>/tests/gpgscm:<path to>/tests/openpgp \
+ $(pwd)/tests/gpgscm/gpgscm [gpgscm args] \
+ run-tests.scm [test suite runner args]
+
+*** Arguments supported by the test suite runner
+The test suite runner supports two modes of operation, '--sequential'
+and '--parallel'. By default the tests are run in sequential order,
+each one in a clean environment.
+
+You can specify the tests to run as positional arguments relative to
+srcdir (e.g. just 'version.scm'). Note that you do not have to
+specify setup.scm and finish.scm, they are executed implicitly.
+
+The test suite runner can be executed in any location that the current
+user can write to. It will create temporary files and directories,
+but will in general clean up all of them.
+*** Discussion of the various environment variables
+**** srcdir
+Must be set to the source of the openpgp test suite. Used to locate
+data files.
+**** GPGSCM_PATH
+Used to locate the Scheme library as well as code used by the test
+suite.
+**** BIN_PREFIX
+The test suite does not hardcode any paths to tools. If set it is
+used to locate the tools to test, otherwise the test suite assumes to
+be run from the build directory.
+**** GPG_PRESET_PASSPHRASE
+This tool is not installed by 'make install', hence we need to
+explicitly override its position. In fact, the location of any tool
+used by the test suite can be overridden this way. See defs.scm.
+**** argv[0]
+run-tests.scm depends on being able to re-exec gpgscm. It uses
+argv[0] for that. Therefore you must use an absolute path to invoke
+gpgscm.
+* How to write tests
+gpgscm provides a number of functions to aid you in writing tests, as
+well as bindings to process management abstractions provided by GnuPG.
+For the Scheme environment provided by TinySCHEME, see the TinySCHEME
+manual that is included in tests/gpgscm/Manual.txt.
+
+For a quick start, please have a look at various tests that are
+already implemented, e.g. 'encrypt.scm'.
+** The test framework
+The functions info, error, and skip display their first argument and
+flush the output buffers. error and skip will also terminate the
+process, signaling that the test failed or should be skipped.
+
+(for-each-p msg proc list) will display msg, and call proc with each
+element of list while displaying the progress appropriately.
+for-each-p' is similar, but accepts another callback before the 'list'
+argument to format each item. for-each-p can be safely nested, and
+the inner progress indicator will be abbreviated using '.'.
+** Debugging tests
+
+Say you are working on a new test called 'your-test.scm', you can run
+it on its own using
+
+ obj $ make -C tests/openpgp check TESTS=your-test.scm
+
+but something isn't working as expected. There are several little
+gadgets that might help. The first one is 'trace', a function that
+prints the value given to it and evaluates to it. E.g.
+
+ (trace (+ 2 3))
+
+prints '5' and evaluates to 5. Also, there is an 'assert' macro that
+aborts the execution if its argument does not evaluate to a trueish
+value. Feel free to express invariants with it.
+
+You can also get an interactive repl by dropping
+
+ (interactive-repl (current-environment))
+
+anywhere you like. Or, if you want to examine the environment from an
+operating system shell, use
+
+ (interactive-shell)
+
+** Interfacing with gpg
+
+defs.scm defines several convenience functions. Say you want to parse
+the colon output from gpg, there is gpg-with-colons that splits the
+result at newlines and colons, so you can use the result like this:
+
+ (define (fpr some-key)
+ (list-ref (assoc "fpr" (gpg-with-colons
+ `(--with-fingerprint
+ --list-secret-keys ,some-key)))
+ 9))
+
+Or if you want to count all non-revoked uids for a given key, do
+
+ (define (count-uids-of-secret-key some-key)
+ (length (filter (lambda (x) (and (string=? "uid" (car x))
+ (string=? "u" (cadr x))))
+ (gpg-with-colons
+ `(--with-fingerprint
+ --list-secret-keys ,some-key)))))
+
+** Temporary files
+(lettmp <bindings> <body>) will create and delete temporary files that
+you can use in <body>. (with-temporary-working-directory <body>) will
+create a temporary director, change to that, and clean it up after
+executing <body>).
+
+make-temporary-file will create a temporary file. You can optionally
+provide an argument to that function that will serve as tag so you can
+distinguish the files for debugging. remove-temporary-file will
+delete a file created using make-temporary-file.
+
+** Monadic transformer and pipe support
+Tests often perform sequential transformations on files, or connect
+processes using pipes. To aid you in this, the test framework
+provides two monadic data structures.
+
+(Currently, the implementation mashes the 'bind' operation together
+with the application of the monad. Also, there is no 'return'
+operation. I guess all of that could be implemented on top of
+call/cc, but it isn't at the moment.)
+*** pipe
+The pipe monad constructs pipe lines. It consists of a function
+pipe:do that binds the functions together and manages the execution of
+the child processes, a family of functions that act as sources, a
+function to spawn processes, and a family of functions acting as
+sinks.
+
+Sources are pipe:open, pipe:defer, pipe:echo. To spawn a process use
+pipe:spawn, or the convenience function pipe:gpg. To sink the data
+use pipe:splice, or pipe:write-to.
+
+Example:
+
+ (pipe:do
+ (pipe:echo "3\n1\n2\n")
+ (pipe:spawn '("/usr/bin/sort"))
+ (pipe:write-to "sorted" (logior O_WRONLY O_CREAT) #o600))
+
+Caveats: Due to the single-threaded nature of gpgscm you cannot use
+both a source and sink that is implemented in Scheme. pipe:defer and
+pipe:echo are executing in gpgscm, and so does pipe:splice.
+*** tr
+The transformer monad describes sequential file transformations.
+
+There is one source function, tr:open. To describe a transformation
+using some process, use tr:spawn, tr:gpg, or tr:pipe-do. There are
+several sinks, although sink is not quite the right term, because the
+data is not consumed, and hence one can use them at any position. The
+"sinks" are tr:write-to, tr:call-with-content, tr:assert-identity, and
+tr:assert-weak-identity.
+
+A somewhat contrived example demonstrating many functions is:
+
+ (tr:do
+ (tr:pipe-do
+ (pipe:echo "3\n1\n2\n")
+ (pipe:spawn '("/usr/bin/sort")))
+ (tr:write-to "reference")
+ (tr:call-with-content
+ (lambda (c)
+ (echo "currently, c contains" (string-length c) "bytes")))
+ (tr:spawn "" '("/usr/bin/gcc" -x c "-E" -o **out** **in**))
+ (tr:pipe-do
+ (pipe:spawn '("/bin/grep" -v "#")))
+ (tr:assert-identity "reference"))
+
+Caveats: As a convenience, gpgscm allows one to specify command line
+arguments as Scheme symbols. Scheme symbols, however, are
+case-insensitive, and get converted to lower case. Therefore, the -E
+argument must be given as a string in the example above. Similarly,
+you need to quote numerical values.
+** Process management
+If you just need to execute a single command, there is (call-with-fds
+cmdline infd outfd errfd) which executes cmdline with the given file
+descriptors bound to it, and waits for its completion returning the
+status code. There is (call cmdline) which is similar, but calls the
+command with a closed stdin, connecting stdout and stderr to stderr if
+gpgscm is executed with --verbose. (call-check cmdline) raises an
+exception if the command does not return 0.
+
+(call-popen cmdline input) calls a command, writes input to its stdin,
+and returns any output from stdout, or raises an exception containing
+stderr on failure.
+* Sample messages
diff --git a/tests/openpgp/all-tests.scm b/tests/openpgp/all-tests.scm
new file mode 100644
index 0000000..d687fe4
--- /dev/null
+++ b/tests/openpgp/all-tests.scm
@@ -0,0 +1,78 @@
+;; Copyright (C) 2017 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(export all-tests
+ ;; Parse the Makefile.am to find all tests.
+
+ (load (with-path "makefile.scm"))
+
+ (define (expander filename port key)
+ (parse-makefile port key))
+
+ (define (parse filename key)
+ (parse-makefile-expand filename expander key))
+
+ (define setup
+ (make-environment-cache
+ (test::scm
+ #f
+ (path-join "tests" "openpgp" "setup.scm")
+ (in-srcdir "tests" "openpgp" "setup.scm"))))
+
+ (define (qualify path variant)
+ (string-append "<" variant ">" path))
+
+ (define (setup* variant)
+ (make-environment-cache
+ (test::scm
+ #f
+ (qualify (path-join "tests" "openpgp" "setup.scm") variant)
+ (in-srcdir "tests" "openpgp" "setup.scm")
+ (string-append "--" variant))))
+
+ (define setup-use-keyring (setup* "use-keyring"))
+ (define setup-extended-key-format (setup* "extended-key-format"))
+
+ (define all-tests
+ (parse-makefile-expand (in-srcdir "tests" "openpgp" "Makefile.am")
+ (lambda (filename port key) (parse-makefile port key))
+ "XTESTS"))
+
+ (define tests
+ (map (lambda (name)
+ (test::scm setup
+ (path-join "tests" "openpgp" name)
+ (in-srcdir "tests" "openpgp" name))) all-tests))
+
+ (when *run-all-tests*
+ (set! tests
+ (append
+ tests
+ (map (lambda (name)
+ (test::scm setup-use-keyring
+ (qualify (path-join "tests" "openpgp" name)
+ "use-keyring")
+ (in-srcdir "tests" "openpgp" name)
+ "--use-keyring")) all-tests)
+ (map (lambda (name)
+ (test::scm setup-extended-key-format
+ (qualify (path-join "tests" "openpgp" name)
+ "extended-key-format")
+ (in-srcdir "tests" "openpgp" name)
+ "--extended-key-format")) all-tests))))
+
+ tests)
diff --git a/tests/openpgp/armdetach.scm b/tests/openpgp/armdetach.scm
new file mode 100755
index 0000000..105f52d
--- /dev/null
+++ b/tests/openpgp/armdetach.scm
@@ -0,0 +1,32 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(for-each-p
+ "Checking armored detached signatures"
+ (lambda (source)
+ (lettmp (tmp)
+ (call-popen `(,@GPG --yes --passphrase-fd "0" -sab
+ --output ,tmp ,source ) usrpass1)
+ (pipe:do
+ (pipe:open source (logior O_RDONLY O_BINARY))
+ (pipe:spawn `(,@GPG --yes --verify ,tmp -)))))
+ (append plain-files data-files))
diff --git a/tests/openpgp/armdetachm.scm b/tests/openpgp/armdetachm.scm
new file mode 100755
index 0000000..27038a0
--- /dev/null
+++ b/tests/openpgp/armdetachm.scm
@@ -0,0 +1,36 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(define files (append plain-files data-files))
+
+(info "Checking armored detached signatures of multiple files")
+(lettmp (tmp)
+ (call-popen `(,@GPG --yes --passphrase-fd "0" -sab
+ --output ,tmp ,@files) usrpass1)
+ (pipe:do
+ (pipe:defer (lambda (sink)
+ (for-each (lambda (file)
+ (pipe:do
+ (pipe:open file (logior O_RDONLY O_BINARY))
+ (pipe:splice sink)))
+ files)))
+ (pipe:spawn `(,@GPG --yes --verify ,tmp -))))
diff --git a/tests/openpgp/armencrypt.scm b/tests/openpgp/armencrypt.scm
new file mode 100755
index 0000000..6d6ec4d
--- /dev/null
+++ b/tests/openpgp/armencrypt.scm
@@ -0,0 +1,31 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(for-each-p
+ "Checking armored encryption"
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg usrpass1 `(--yes --passphrase-fd "0" -ea --recipient ,usrname2))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity source)))
+ (append plain-files data-files))
diff --git a/tests/openpgp/armencryptp.scm b/tests/openpgp/armencryptp.scm
new file mode 100755
index 0000000..4bcc058
--- /dev/null
+++ b/tests/openpgp/armencryptp.scm
@@ -0,0 +1,32 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(for-each-p
+ "Checking armored encryption and decryption using pipes"
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:pipe-do
+ (pipe:gpg `(--yes -ea --recipient ,usrname2))
+ (pipe:gpg '(--yes --decrypt)))
+ (tr:assert-identity source)))
+ (append plain-files data-files))
diff --git a/tests/openpgp/armor.scm b/tests/openpgp/armor.scm
new file mode 100755
index 0000000..3c117dd
--- /dev/null
+++ b/tests/openpgp/armor.scm
@@ -0,0 +1,767 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(define armored_key_8192 "-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: SKS 1.0.9
+
+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
+=oXxa
+-----END PGP PUBLIC KEY BLOCK-----
+")
+
+;; Bug solved 2005-04-07:
+;; Try importing the attached key file. As the key is exactly 8192
+;; bytes long, radix64_read is called twice - the first time to read
+;; the 8192 bytes, and then once again, to handle the pad '=' on the
+;; last four character radix64 block '0uI='. gpg bails out with
+;; gpg: [don't know]: invalid packet (ctb=2d)
+;; On a read for only the = sign, radix64_read returns -1 for EOF.
+;; This causes the iobuf code to pop the armor filter and thus the next
+;; byte read is the '-' from the END header line, causing an error.
+(info "Checking armored_key_8192")
+(pipe:do
+ (pipe:echo armored_key_8192)
+ (pipe:gpg '(--import)))
+
+(define nopad_armored_msg "-----BEGIN PGP MESSAGE-----
+Version: GnuPG v1.4.11-svn5139 (GNU/Linux)
+
+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
+jnOKMUrdbDkbYM+ojXZ18/4WPKtaxf6lTLrh3m5CJ1V8slRJp0Jes74aDQf/OXqo
+QgqVrI2wnl1klGwn06bhVaymdk0hMkxAfeHBGZIQ4BMMZ3aLuVWjAcBH/HP1tVQ4
+IG7MHRnm81yVNgA6yAuZZIPQwxDWVko7rRm/DnsJcpKfL0nZHoF+bJ6q4Rd6Dey1
+S96L4PDmXseFkVZOH/7dNWyKuvSA/MmthkN14lWJiYJebaXb7oZG3XDC70o7bG6Y
+mtGOrOwVthFereg1Ii98ZA4nKgqeu2paMju/t03hQXHY5iqyV9ax0A3B0rdivz4U
+VbqCcO7pGNb/Ki3gGc3hfVw9YXnR7E+tra19eE7UM7o+YlunKF1Q5dJaLKY1z3L9
+3UAJmXG/sZcLqrDn9zHfb/YxqbyIkM7VIU2kKztWCCNiNKgLQsIoVzK4sbS2LVDI
+grmvZg+Q7EkwxZ1FXeBGJmsiyjKYPU3PI8ZBU1MXjwTjtnQRuBSxh+Ok9glPeE+1
+rUDdlVoogUGgPAvLV3BM43E/Q5VE+X04KvPNKINvvS1nZpGKyyy1MayOfstc7Hsw
+W/RgllTEd7VW5jgZKg7YyA8r8cUjMqE7zewrq6MtkoFk6ZVslWxfoADBW3ivwdwe
+I4XwNboOgBx77qxf95aHRRdqWZa0JF8zvK5BH6EpBI29hlJU4leax696ACA7QIIM
+Rpc+ulkvHsNxsUlrUut9AXoob0MqDJRmZvU4gSVivHjvKLEIlymJw4pLbMWhcrNa
+v94TExP21Fy/zYcWiZT2nCX6qZVXTcUcQGIrBTWDbR8bxKll4FNo/2zmelyFmeXt
+iH+Zp2EwFAUELsrxx9plNd5WceyU9VnZoeucNFd2QFl7lV9KL8AlQaaMdsYOt27m
+8j7iNBID4HtCYM0xLwE/5uqVQPxX6qzPPZc66MSRIi8ZHZPFvVilFVzFyZSrq5Lo
+ojQQmAycQGOzx7dwx7vi9SeTrBRY2PK3WVurcLiRxM+2u9vjlxigwimpnK3VU1dh
+GDoPghB3O34bfiV5GndcnPDLJxsSGWz2z2WiyCFgCkVp3shHUN5c2PLWDIOf/Ejz
+LzNJXFKjO6/6ZGpMmGf6bZCa9MBnvXMNic9/k0lmtbgj8SS+2//gko1EDa/Gpaqo
+J2xgEuHLvp9KQABWt9VRI+tNUJQCS/Jq10ZiT1TzhczyJEqbtVDOo0l5A5sMV0PO
+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
+=3akT
+-----END PGP MESSAGE-----
+
+")
+
+(define alpha_seckey "-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1.4.8 (GNU/Linux)
+
+lQHhBDbjjp4RBAC2ZbFDX0wmJI8yLDYQdIiZeAuHLmfyHsqXaLGUMZtWiAvn/hNp
+ctwahmzKm5oXinHUvUkLOQ0s8rOlu15nhw4azc30rTP1LsIkn5zORNnFdgYC6RKy
+hOeim/63+/yGtdnTm49lVfaCqwsEmBCEkXaeWDGq+ie1b89J89T6n/JquwCgoQkj
+VeVGG+B/SzJ6+yifdHWQVkcD/RXDyLXX4+WHGP2aet51XlKojWGwsZmc9LPPYhwU
+/RcUO7ce1QQb0XFlUVFBhY0JQpM/ty/kNi+aGWFzigbQ+HAWZkUvA8+VIAVneN+p
++SHhGIyLTXKpAYTq46AwvllZ5Cpvf02Cp/+W1aVyA0qnBWMyeIxXmR9HOi6lxxn5
+cjajA/9VZufOXWqCXkBvz4Oy3Q5FbjQQ0/+ty8rDn8OTaiPi41FyUnEi6LO+qyBS
+09FjnZj++PkcRcXW99SNxmEJRY7MuNHt5wIvEH2jNEOJ9lszzZFBDbuwsjXHK35+
+lPbGEy69xCP26iEafysKKbRXJhE1C+tk8SnK+Gm62sivmK/5av4CAwKcF1Qep+Pf
+ssOqtJhr+klruUBf55onBJi4vkk0gK3m32p/05YB2bbMURGz8R4JxUZfUxjdDk73
+LaNYRbQpQWxwaGEgVGVzdCAoZGVtbyBrZXkpIDxhbHBoYUBleGFtcGxlLm5ldD6I
+VQQTEQIAFQUCNuOOngMLCgMDFQMCAxYCAQIXgAAKCRAtcnzHaGl3NDl4AJ4rouHB
++LpCkNi5C59jHEa1kbANzACgmddtrNSj1yPyTCwUwRghPUomECS0EEFsaWNlIChk
+ZW1vIGtleSmIVQQTEQIAFQUCNuO2qwMLCgMDFQMCAxYCAQIXgAAKCRAtcnzHaGl3
+NCeMAJ9MeUVrago5Jc6PdwdeN5OMwby37QCghW65cZTQlD1bBlIq/QM8bz9AN4G0
+J0FsZmEgVGVzdCAoZGVtbyBrZXkpIDxhbGZhQGV4YW1wbGUubmV0PohVBBMRAgAV
+BQI247hYAwsKAwMVAwIDFgIBAheAAAoJEC1yfMdoaXc0t8IAoJPwa6j+Vm5Vi3Nv
+uo8JZri4PJ/DAJ9dqbmaJdB8FdJnHfGh1rXK3y/Jcp0BuAQ2448PEAQAnI3XH1f0
+uyN9fZnw72zsHMw706g7EW29nD4UDQG4OzRZViSrUa5n39eI7QrfTO+1meVvs0y8
+F/PvFst5jH68rPLnGSrXz4sTl1T4cop1FBkquvCAKwPLy0lE7jjtCyItOSwIOo8x
+oTfY4JEEXmcqsbm+KHv9yYSF/YK4Cf7bIzcAAwcD/Rnl5jKxoucDA96pD2829TKs
+LFQSau+Xiy8bvOSSDdlyABsOkNBSaeKO3eAQEKgDM7dzjVNTnAlpQ0EQ8Y9Z8pxO
+WYEQYlaMrnRBC4DZ2IadzEhLlIOz5BVp/jfhrr8oVVBwKZXsrz9PZLz+e4Yn+siU
+Uvlei9boD9L2ZgSOHakP/gIDApwXVB6n49+yw6e5k2VJBGTFDkQbxpgi4oslePpT
+7Tc2qjAke4zO8JHkgKSokEgnMpMz412q9otFX/3qC5MpPG5P8f4r00Kfy9Am/thk
+ri01WTIUqF8L/VZXJxLKVoRAabSXudG0eavfah14fN5/+Bw5i8vSHhc/xmQEKTya
+2X8Nt1F5zMrE1LAGVVCL9i/DUygnJYOZzAd1Ct0RJ4kFj7lOBICF2IWWiEYEGBEC
+AAYFAjbjjw8ACgkQLXJ8x2hpdzQgqQCgn81AaW8W/lyVwMh/UBeMuVMUb24An2uz
+wg7Md81a5RI3F2FG8747t9gX
+=VM1e
+-----END PGP PRIVATE KEY BLOCK-----
+")
+
+;; Bug 1179 solved 2010-05-12:
+;; It occurred for messages of a multiple of the iobuf block size where
+;; the last line had no pad character. Due to premature poppng of thea
+;; rmor filter gpg swalled the CRC line and passed the '-----END...'
+;; line on to the decryption layer.
+
+(info "Importing alpha_seckey")
+(pipe:do
+ (pipe:echo alpha_seckey)
+ (pipe:gpg '(--import)))
+
+(info "Checking for bug #1179")
+(tr:do
+ (tr:pipe-do
+ (pipe:echo nopad_armored_msg)
+ (pipe:gpg '(--decrypt))))
diff --git a/tests/openpgp/armsignencrypt.scm b/tests/openpgp/armsignencrypt.scm
new file mode 100755
index 0000000..97595f0
--- /dev/null
+++ b/tests/openpgp/armsignencrypt.scm
@@ -0,0 +1,31 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(for-each-p
+ "Checking armored signing and encryption"
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg usrpass1 `(--yes --passphrase-fd "0" -sea --recipient ,usrname2))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity source)))
+ (append plain-files data-files))
diff --git a/tests/openpgp/armsigs.scm b/tests/openpgp/armsigs.scm
new file mode 100755
index 0000000..ccab816
--- /dev/null
+++ b/tests/openpgp/armsigs.scm
@@ -0,0 +1,31 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(for-each-p
+ "Checking armored signatures"
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg usrpass1 `(--yes --passphrase-fd "0" -sa --recipient ,usrname2))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity source)))
+ (append plain-files data-files))
diff --git a/tests/openpgp/bug1223-bogus.asc b/tests/openpgp/bug1223-bogus.asc
new file mode 100644
index 0000000..469e6b9
--- /dev/null
+++ b/tests/openpgp/bug1223-bogus.asc
@@ -0,0 +1,21 @@
+Bogus test key for bug 1223 (Designated revoker sigs are not properly merged)
+Thanks to Daniel Kahn Gillmor for providing the test keys.
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+mI0ES+OoSQEEAJUZ/+fC6DXN2X7Wxl4Huud/+i2qP1hcq+Qnbr7hVCKEnn0edYl+
+6xfsKmAMBjl+qTZxPSDSx4r3ciMiIbnvXFtlBAQmji86kqoR6fm9s8BN7LTq7+2/
+c2FHVF67D7zES7WgHc4i7CfiZnwXgkLvi5b1jBt+MTAOrFhdobxoy6/XABEBAAGI
+twQfAQIAIQUCS+OsRRcMgAEAAAAAAAAAAAAAAAAAAAAAAAAAAQIHAAAKCRA0t9EL
+wQjoOrRXBACBqhigTcj8pJY14AkjV+ZzUbm55kJRDPdU7NQ1PSvczm7HZaL3b8Lr
+Psa5c5+caVLjsGWkQycQl7lUIGU84KoUfwACQKVVLkqJz8LkL54lLcwkG70+1NH5
+xoSNcHHVbYtqDLNeCOq5jEIoXuz44wiWVEfF+/B115PvgwZ63pjH1rRGVGVzdCBL
+ZXkgRGVtb25zdHJhdGluZyBSZXZva2VyIFRyb3VibGUgKERPIE5PVCBVU0UpIDx0
+ZXN0QGV4YW1wbGUubmV0Poi+BBMBAgAoBQJL46hJAhsDBQkACTqABgsJCAcDAgYV
+CAIJCgsEFgIDAQIeAQIXgAAKCRA0t9ELwQjoOgLpA/9/si2QYmietY9a6VlAmMri
+mhZeqo6zyn8zrO9RGU7+8jmeb5nVnXw1YmZcw2fiJgI9+tTMkTfomyR6k0EDvcEu
+2Mg3USkVnJfrrkPjSL9EajW6VpOUNxlox3ZT1oyEo3OOnVF1gC1reWYfy7Ns9zIB
+1leLXbMr86zYdCoXp0Xu4g==
+=YV5g
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/bug1223-good.asc b/tests/openpgp/bug1223-good.asc
new file mode 100644
index 0000000..5622cb3
--- /dev/null
+++ b/tests/openpgp/bug1223-good.asc
@@ -0,0 +1,20 @@
+Good test key for bug 1223 (Designated revoker sigs are not properly merged)
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+mI0ES+OoSQEEAJUZ/+fC6DXN2X7Wxl4Huud/+i2qP1hcq+Qnbr7hVCKEnn0edYl+
+6xfsKmAMBjl+qTZxPSDSx4r3ciMiIbnvXFtlBAQmji86kqoR6fm9s8BN7LTq7+2/
+c2FHVF67D7zES7WgHc4i7CfiZnwXgkLvi5b1jBt+MTAOrFhdobxoy6/XABEBAAGI
+twQfAQIAIQUCS+OsRRcMgAEO5b6XkoLYC591QPHM0u2U0hc56QIHAAAKCRA0t9EL
+wQjoOrRXBACBqhigTcj8pJY14AkjV+ZzUbm55kJRDPdU7NQ1PSvczm7HZaL3b8Lr
+Psa5c5+caVLjsGWkQycQl7lUIGU84KoUfwACQKVVLkqJz8LkL54lLcwkG70+1NH5
+xoSNcHHVbYtqDLNeCOq5jEIoXuz44wiWVEfF+/B115PvgwZ63pjH1rRGVGVzdCBL
+ZXkgRGVtb25zdHJhdGluZyBSZXZva2VyIFRyb3VibGUgKERPIE5PVCBVU0UpIDx0
+ZXN0QGV4YW1wbGUubmV0Poi+BBMBAgAoBQJL46hJAhsDBQkACTqABgsJCAcDAgYV
+CAIJCgsEFgIDAQIeAQIXgAAKCRA0t9ELwQjoOgLpA/9/si2QYmietY9a6VlAmMri
+mhZeqo6zyn8zrO9RGU7+8jmeb5nVnXw1YmZcw2fiJgI9+tTMkTfomyR6k0EDvcEu
+2Mg3USkVnJfrrkPjSL9EajW6VpOUNxlox3ZT1oyEo3OOnVF1gC1reWYfy7Ns9zIB
+1leLXbMr86zYdCoXp0Xu4g==
+=xsEd
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/bug537-test.data.asc b/tests/openpgp/bug537-test.data.asc
new file mode 100644
index 0000000..b6b02e9
--- /dev/null
+++ b/tests/openpgp/bug537-test.data.asc
@@ -0,0 +1,960 @@
+This is a binary (gzip compressed) file which exhibits a problem with
+the zlib decryptor. See encr-data.c:decrypt_data for a description of
+the problem we solved with 1.9.92 (1.4.6). It is not easy to produce
+such files, but this one works. The source file is also in the BTS
+under the name check-data-410-1.data. The result of the decryption
+should yield a file with the SHA-1 hash
+4336AE2A528FAE091E73E59E325B588FEE795F9B.
+
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v1.4.5 (GNU/Linux)
+
+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
+qgtkR/1FowOQkyE=
+=5l5y
+-----END PGP MESSAGE-----
+
diff --git a/tests/openpgp/bug894-test.asc b/tests/openpgp/bug894-test.asc
new file mode 100644
index 0000000..11223ea
--- /dev/null
+++ b/tests/openpgp/bug894-test.asc
@@ -0,0 +1,565 @@
+Test key for bug 894. segv when importing certain keys with duplicated
+user id.
+
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: PGP Key Server 0.9.6
+
+mQGiBD2CgM0RBACJLGH4VS1F+MEyE3hEDk580pmeLZl32nLUTGtGc0YBtfjiBkjD
+XnPHF1sbp3FLAYdKOZHY/4efGmGE86L9L5y1Uxuqgzi7c3jze27bp9bBKSQWMVIT
+iIXGnjNXNuZUCkhhKXCHBy/2x7J5jYdZYigU+a4vrhXgTdLJNpamEx7uRwCgnHFd
+8pImqdGJMUhGH5qJ8tdOZP0D+wSgY5U6f3GyC98c7HgtHoIHwTBR4DGmdHEZ2w9W
+xAsZhu34PsmVqWmkzzFQdzkjQq8Bxorrjn8MYRUZDhd/dYU+Xyk49IAdZVFnMOEO
+v2VyZLVwfjbIJK73g8otU3W538XXFhkUR9/cnuXTBWiUfizmIpzkbjaSpqMl1i99
+KY1YA/4+DX/nlFLemtZh4AH3RSeo5RQ6WJhFtuL5Vy7jWPFmInHktfx7Tpkq0qa2
+8oUK8pisNywZySd+iClgS+gkTNmPwbwTI6EGAznUgZB8bQpHgNMN+ENBPDYVhzdM
+OYmYr1WCKsFK5DYUp4iZLmyrvojOH47ZdbW7TXnzyUI7459AnLQdS3VydCBMaWVi
+ZXIgPGt1cnRAbGllYmVyLm9yZz6JASIEEAECAAwFAkHLzREFAwASdQAACgkQlxC4
+m8pXrXx0rggAw7ibX85WpgzNMqPHGbJ3ZBVgSdGwDM8J/ucklREzX7HVoGe5XYld
+6aHklODEJa/ng7Y+8fASDgdszgaNjUwD508EufNkC8rlUrFb89GGSqe2cEIOAfXs
++gcD3u8EkhJnzaGHmaeMSNLsmTuMVR6yN+M9olIdLO5ZZca4uhqmaOtIWSBmkHI1
+CxWRhE0HUzmZRY3tQYnujUDlDa5NIUJieVLBOKlnb+VXAIZDfgRvKM4MTZFv4o31
+G0Op7/7MvKz/rI26kjPkwWSn9O8oZ3HvYv/mghdova2Gg2GmWaRN3Q3IZmQHY7cf
+cC25NKoEyFO85fP5SnaoKev2Fr0F1m/ApYkBIgQQAQIADAUCQdzzzgUDABJ1AAAK
+CRCXELibyletfOrrB/4h3TJERSzaDFHi7d3q/gKC5oOxziMCYjrn8lQfDsg9ge8u
+1haKq1VfrmpntY26G7iJ9yS63/Vt08/4ZL1R8pMZryHtcrSXMW9uYp8BPf+QlWDU
+P4jk5JeAnpQ95r3SSE8YOAnGWDp0PpT00i4hGwgm+gCT/x0qXJhKvoElGZpUztUO
+uSNMb32XwZmE68RFDQybcXHzPc/MPp+AzFhhjjL3PutYagpzRoO4PzfTure2XkGY
+JcOteJj/TLtmSqBOPUgIx7H+H/3vCwA+pR1iiBSQFsyftpFsaFFuXg7YGXezVw68
+UC0UImP83L7RmBrqOCNQ8wcd4ecyUxFfCy7itPitiQEiBBABAgAMBQJB7r0RBQMA
+EnUAAAoJEJcQuJvKV618gg4H/20TTjWQta0HjYAK3H5xNSogkZyBg4eQT/5xW4/K
+QKNwBSAV4belVJ4tkVw57mOm5f1VzKf+efm5TR80g94R/wMsAkKsgxAr6pHE4h10
+fVmX+IFc2Ba3NNWWAda5dugGA5NT2QM6vo657uN9Lhy0yaRcEvcjYjGPghCq8L99
+qoRzKK1wdAOsE/3vbpG6vxPvjxJD+BkkwCEGefwWtHs//xFOUJUPddTd1yqrikaV
+BbuTpFhUmRIQmpuAIQWaBxusKR+Om/puUpsHvcj2jBSXR96vMPyV66F6eRGk4H50
+MtevNGGlxrLKhQjP139PEcwA/JT65NZfpqKiv4wmaaWpv+aJASIEEAECAAwFAkIA
+iWUFAwASdQAACgkQlxC4m8pXrXy2dggAmaK7DuKFWTpq0SV3UpZJxV1lFykxiTlj
+TnFdHH9KJtB8nPAKUc9xeAjhpuJmJRwUXDdpVOEPdpi/AHz0YCQI8wTosWroZQLL
+tSWFlrCLVDqYvlS5ushMvEl3HtnO7Foe2LynEplb7NDcGTlLUSldSHJ8I8q0Bppa
+dBNaV94xPxBTIn8PXU1EvJ3fCL+FuA3M0tWqPCn5A4xRCJEFwbahsry0jrR4z2T+
+YvvW4o6wvsKVpBonbqp7bNA0qnk+pqL3xYDuw47YRHi1tfYCZvJjEcs9M/ZhSHNB
+MfHB5wkHrPC/1JFDAdQpTCxKEDT3LQLSUzxOuQmn6GPQ5iSMDBtqIIkBIgQQAQIA
+DAUCQhJVMAUDABJ1AAAKCRCXELibyletfIysCADCgXmHxaTTbrq2ut9ShOzeNMiy
+9jX69O9eDaADteQyWY9CeLy/XtUPorLS0fmdq1igf8u0e6mLUAzgzLKG5UXzcc2D
+Slabinr6SXaVcmmR8wc63uUZaNasYoG6xjuSiABMJvnwUwQGPkGSct1Ne1O65r5m
+JYswxO/ou+sZNBHt+uCgDmAquocw6T1KFHXm6WBLfZMv1y0pca9rhaM8N8AG8AeE
+9Dwvi5ObIOWgzUE5k//F29Ynq4AKANAl69N7xoACn8SyKMr/XNhioq+jbHcgx0LN
+nx/xl40uOvOsQJ3xxG7lhaTMcgYpldadluckzNvEva3SqcvW+UQQstFivbVliQEi
+BBABAgAMBQJCE7kMBQMAEnUAAAoJEJcQuJvKV618eVwH/j2fAhyzUzWREWxSQsHD
+JQZWRCR1Bm7gX5RhuYrFWfLmHdEua9TdOl5z+DCJoXJyJcPfhj+N0gzfs+mLx2j6
+QyN6xVAMKLAy1lwxbVxwqnUhWnHTKMgDQkLs+WSzM6ZGGFdg0aoOZtuw/mPe9I25
+ARhCDRgClzT1YLQmcuueNohOfU5uXEDrJPQii7El1hpzenfLimBluE8r2MhZJZxO
+vNuub2TDbJir54N/cu6GV3jYEFCOXj3cW2JalyEiewbwEN1ZfChym3TLCevP5ItY
+90jKIdUR3EN1CrUzbPWF6Q0RsUbwlWYaXXDUfmojKUelcY5CQhkkaZ9CcPe6sVgs
+ZrCJASIEEAECAAwFAkIWrQgFAwASdQAACgkQlxC4m8pXrXySOQf/YsZiUyM4PfDy
+e9ZTNeC2KCK6xpvGW7suxMfZFHVMpV5J0ZtKWqUsPNDx/6f/SiroK/3/TGz+eACn
+CZXPpgraGwwwHn7nvtekYkX03ozO+XGY7QRlMf4sYHV6JsCxR14q8BBrjcUQpwnt
+dBQYQQV6OddwxqnCzGdWKSebSRE30xRRzYyPZsGuDmTZXuH1kaLS+qxGst0O8vS/
+Ht5PLI3BYbIoCU5H0tMiQoQrAeqSoZmaipVu65iXSeXCpR82wVgqqlyXDt+Euho2
+dW8ib3ilKa5oB8QJ3NicM7wYZd+lipvcGuX7iLtHi+iSCRrYhJDaTQVFsbSclYsv
+jWJolCuwoYkBIgQQAQIADAUCQilwqgUDABJ1AAAKCRCXELibyletfNJEB/9AGg0Q
+mH4iYNL3KeVx+0U6j9D82spXWUPHaacXnjj8k93FmwcO4qW8WaNuFZlOaayitCJ2
+QsxwYV1Etonu92RPbTQqYAvKjAx8NcXYBj6zG5PbgHIGE8NOKdLIgkqsJgSDn47/
+2IjGGwxrrECYlKn6aLcRKlD3t/zd5XgLz8mIUkXPOfeCmzlCZkarf2n+/5OaTyKV
+nxu9wJrQykQ7PbbiK6/oG9ZYhjk6zN7tW7ZM8eYQjn4L3x3Ht06XdLMFb1nCHSrn
+BK34FnBO19k4CDZLtD7zeLf1asYrNvX1ij2KvzFCW9KQoA2MIYB1LDsn4nuE/2Bv
+tkLxU+BMjCfMZ9GniQEiBBABAgAMBQJCPTR1BQMAEnUAAAoJEJcQuJvKV618byEH
+/3D/z5vcgXyNrkqfmhACLv0qM2w3Df3t9+b5zDRTQC/QB+tY250Ylg/5tamqYhKi
+QvOm4fMvmDOFEngSxcv3aDEtrfZf/SBX/AGdOKlDOtLLcaV3r1wZzCNEb4NrOpEq
+/zQkUETUrahwLXEt3H3gJoDIcU/uRKswGXdrl1SjjCVjrgupYet8hqP8Xd6MjEef
+U5xrtYQIee19K2Fx2UcfVATyoGapqnCFnqBfM8QXvQHwmFMmk5nZMED1oN0hn/qu
+1BKCb9xjsXk0VoVz0vFOM7ICHjbJrwbaaFjGBkIgI0GmGCJbPjCW6qqBYlGSb1zp
+VoPJn/Gauq+ypYyA1E+W4qSJASIEEAECAAwFAkJPqcgFAwASdQAACgkQlxC4m8pX
+rXzIuQgAySTWpeSv7PQ8wiXpeFTJnAhqC/gEIBdoRxOYMvcvJCWmMynDrymM0AU3
+A3aF/Mb95UaVb+A7co+fdlkcA/cge1ksQ1FmeoN141nQ7u2NknPaGwNSwQ1t1DRL
+9U2O+0VKtk2TowR4Ado4bzwgVsFvCm9Tfpa6IDip/BGdpjfLDN5XBBhJRIl0DYjT
+0ui2nuA7YFBfAW6ErxV2P88d/+2aJBux4A61KMtQrOOkclDZa/EOD20sn6B5gGYf
+JKb8VUNWgjOsq1WJ+2prmrHbSEqmqWtkoLPZYQl+yoJjTizfao8s0fA28YdATyk5
+eryog4X+Y8wZOk0r4Dp3BW7xWXAei4kBIgQQAQIADAUCQmIT4QUDABJ1AAAKCRCX
+ELibyletfJkkCACGnLYlBrQmrVMiQoIUMo3F0GhhrrgoIpP8vKu0WM/bW5itSE0D
+wzZDyyMdeSa5tYWCy3WjYHuUesC0g23jE9hP0gghvNAMcl8kieqFRPZFBqHyokZ6
+3m2y8cQT5AkwJFPosUjIaGkVmtzmBfsDBZdHve6HgnMEgotjnyCqscFvg2IDW5fr
+2lN/fgazqOnV/NKN2kkodJp7s1cT3e40+PsU9cukrxLJSbcYi2YDMRoIQ80tJk+q
+UoAGFDGfSx4/bWu1E/8X8rBBzkrBn5B+Wl2EwDfVI68YkU7AX69Xy+GhJYnWDWFV
+tISxktIHUYUa3OxF9KUFsI4w2YCzPNHKaSUfiQEiBBABAgAMBQJCYrzcBQMAEnUA
+AAoJEJcQuJvKV618iAwH/2pXT3uVaMCkRTN9p2R1s4GAS9A2hi2N0hKdWw4EJdbX
+M91RDxi+ZjhzEeUgWnWYTi+Bj0kKyyPxeVDQ2qaq2anEyXkV5MqVgJIqYTEq9nD0
++NBtU2zrVPVpl1MIXmws3++/JxGin/33f0ZVP8C/1DePGywblULM75Di368wHt/Y
+dFSSOWpfYZvCkh/Bvqf/4BTRu7BSci6OTKA+B3kNK7g9Wdy1zGfR0wtuHWBcD7rJ
+pZJqs90rUFnLXS3FYl0yGuLy/l+yOXzlTZF4vTgMtGmSqAcXOfpPKud/SheAP7Nt
+Vbin47rVxOcdNcEu+vx2EajxhSG8hzeVcmFYzOa0qZqJASIEEAECAAwFAkJ1MGEF
+AwASdQAACgkQlxC4m8pXrXyqDAf/RcKNNbobfnoJnI1VqhPVBCdffHOftLB1c/YU
+4KDt/PKB7s+UlmCLuC7LAuLBDa/AyyoUlMkYMHJq6WLJqxhIrc6l0g9lLEpEh2hg
+Sd5zV/cR3Aj26m7pQAGQf0SCruVtnFq45yY5PJtViOZ1knr0i0IOg2FZ6dF1hATG
+IZVahsYGf5Q6ls8IVU3KR0KzWYAvUWC4upXqqdoY5ykouAI+Gce6AQka6hMy7mbL
+/ySduzDdpDDiMRdjObajR9wsHErUrwPlGzbr6KscjeZtJoEoqu5HT4Ab2PQ10RJQ
+IJcxIQQVTcQeJJwIZdvK7v87wmwrwIiaBYw6f0kCFMBuGhURqIkBIgQQAQIADAUC
+QocBRgUDABJ1AAAKCRCXELibyletfL8ICACg0KtUwDWLTAR2qQyHNFTLX+PiScTc
+pC5kHHTj4zWyWW9eC1sO8lUqVB+3jAgckav62iVgyv7Gl+4vizBqOvjBh52C4BIR
+3lkpzZ2gQdnIXOw3WGrpiPSahY/fFvk7VE0vHqcbnO91+F2MvHcZxqWsPflag0TK
+ois1CmBXTkOO6QTtxS1xGvPAImmfb0XzIbZ/C7F5szvYHLBpz6cHdWvG8hJHI9+3
+y21i7ZkpzHAc6TwgGcXvTpPOSUU4jgS7IDu4Hs0Vd7MjK3F4R8QFPE+hWzLIQIOh
+6Ds1VFU0pgVsVuXkrvjgFsgXyfebp7FmdWVSKMbN+r6rkhjxGWimWrUNiQEiBBAB
+AgAMBQJCiaUGBQMAEnUAAAoJEJcQuJvKV618olUH/3mMp7GYIDAVLBxUGism5/VF
+Fm7gSW9ezNf7nquJU4W3aQanU44coKOBChD+ZVScOdXV4dD/gM4SzgVGiT01jyHh
+o/87165+fuqFKjCTsDFBbDR/bbIsseVVway4ixEQJ5eH1Pwhh1ErJdsWShBNvtvj
+j+ClTvCvc0iH4IVQJyir7rNdwKtDTd/YyNMRro6cF1bIp3bpr0bvAxZLF1eBp95C
+bdR+3t42Yb+mTGMBsmSXUm32sZSHnXs6De/r4moWM5VKqHrxguOwr8TjsM3vFK9b
+tw0cO45H4UzTVe1KRWlmrWZ2kG0cUBJsLUSHTSXJ4IeMVJ84VwAb6Hdxmv8MCSOI
+RgQQEQIABgUCPnnDVQAKCRBW9CvswNf60/4nAKCZ21TN3O44Oz9L75Ev5FL8QxLX
+0QCgqOdcSK+Em70sLqevTA8TqaE/zdWIRgQQEQIABgUCPwbGKQAKCRBEIH0YQ8qw
+NeJzAJ49aclqMXfGuV21ph6fyMzyD83rvgCeLDxPbXBQ/saVk+nuWuAtQs6JAZuI
+RgQQEQIABgUCP74pKgAKCRC3f/OHPJ47d9G8AJwOE6/AtcpPI42Ro+qRgou9nyat
+yQCeKCnvyNgRxrUCSVPJtBZKCjlx+gWIRgQQEQIABgUCQHZrCwAKCRAVYGGs2I/J
+NITZAKCPrXQth0d85BGYbdAsqyQwdtAzPACgjIcQ+LML6kHSDFqWkyEZgutZdhmI
+RgQREQIABgUCQILxlwAKCRAODE9jbmXTJX95AJ4wGxwsVaZEgQbsVwA19S3VPiUj
+BgCghPpy39/JvijAYW7lm1nuxLaWMgWJAhwEEgECAAYFAkB2VUgACgkQHh0RbLTm
+cZQkjA//RtBpVxskkKz5uC0hZKQ1pmlYixXItbBL7qwnV9VkY/c1te1IQh5FT0aJ
+KuSA95bFhs1UP0wCuHDLmsGCeYb/Ij/EinEU/4+Qn1NuLG6PZ1zj+yT6mRJJek2R
+3cM1XSv/rAYeCP25u19yw/nBI+bSU/r1uZaOJFuy0DVsurMa73k5Mxr3cRceikzT
+RR+M3CAh264E4HA1AUDr6CAhYxBjjERfH7hwsJL6JMScnbxgbYFq9S6lJWjFd+As
+j/c35K1tON43b+dhd0C6kn+8v09bMTJjrqrjy0t0wEhntlghDruHY5KelbhOiPVq
+pjU7TI+1eWg0mAtdAWGWaWFi6/uwUWCQD/G246LSBfQHdZDXFjT61YBvFvEnpb0e
+Xx4E6RQJ9icBF8ckjWfEu8ghvwHTAqt1qAuWsAFqKgAfYlnOkZZTwG3v//xIALih
+2KfiuRD0qPfJF8ScBHvhl21h/jfy96zJEsFadwaVDZ+pV6hsR0Ii02r2S+UGcLYF
+7Nhxv9dGm5sjMzo41QF2RjG8RV5ekogAH8f3ysE3BgyqKmeMhKizKR35GvVL9vjj
+Ia4UhGiUWbCbutpFVMxV1saQ8uG62LVituoTEgruz1CFdnQcEP52X5WTya7Xh0uo
+ciMF5Sx+9t86j9Aic34MeRaoe42zlfx0p5Hl1KuLkCqBYc3nf3+JAhwEEgECAAYF
+AkB2VUgACgkQHh0RbLTmcZQkjA//RtBpVxskkKz5uC0hZKQ1pmlYixXItbBL7qwn
+V9VkY/c1te1IQh5FT0aJKuSA95bFhs1UP0wCuHDLmsGCeYb/Ij/EinEU/4+Qn1Nu
+LG6PZ1zj+yT6mRJJek2R3cM1XSv/rAYeCP25u19yw/nBI+bSU/r1uZaOJFuy0DVs
+urMa73k5Mxr3cRceikzTRR+M3CAh264E4HA1AUDr6CAhYxBjjERfH7hwsJL6JMSc
+nbxgbYFq9S6lJWjFd+Asj/c35K1tON43b+dhd0C6kn+8v09bMTJjrqrjy0v/////
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//////+IRgQSEQIABgUCPhkNSwAKCRAXOrFG37Nm8m+5AJ971mhmPMA/x/OKCp84
+55CgtGndhwCeKztNwbBEIjsZ7oqdqmHchoz4a3SIRgQSEQIABgUCPrZbygAKCRAd
+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
+AKCV+pcs+/Vww9F1+M5vQ19tfd8t3g==
+=HtIh
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: PGP Key Server 0.9.6
+
+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
+IM4K+97xXMM=
+=STHU
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/clearsig.scm b/tests/openpgp/clearsig.scm
new file mode 100755
index 0000000..b1c72c2
--- /dev/null
+++ b/tests/openpgp/clearsig.scm
@@ -0,0 +1,108 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(define (check-signing args input)
+ (lambda (source sink)
+ (lettmp (signed)
+ (call-popen `(,@GPG --output ,signed --yes
+ ,@args ,source) input)
+ (call-popen `(,@GPG --output ,sink --yes --verify ,signed) ""))))
+
+(for-each-p
+ "Checking signing and verifying plain text messages"
+ (lambda (source)
+ ((if (equal? "plain-3" source)
+ ;; plain-3 does not end in a newline, and gpg will add one.
+ ;; Therefore, we merely check that the verification is ok.
+ check-execution
+ ;; Otherwise, we do check that we recover the original file.
+ check-identity)
+ source
+ (check-signing '(--passphrase-fd "0" --clear-sign) usrpass1)))
+ (append plain-files '("plain-large")))
+
+;; The test vectors are lists of length three, containing
+;; - a string to be signed,
+;; - a flag indicating whether we verify that the exact message is
+;; reconstructed (whitespace at the end is normalized for plain text
+;; messages),
+;; - and a list of arguments to add to gpg when encoding
+;; the string.
+
+(define :string car)
+(define :check-equality cadr)
+(define :options caddr)
+
+(define
+ vectors
+ '(;; one with long lines
+ ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyx
+
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+" #t ())
+
+ ;; one with only one long line
+ ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyx
+" #t ())
+
+ ;; and one with an empty body
+ ("" #f ())
+
+ ;; and one with one empty line at the end
+ ("line 1
+line 2
+line 3
+there is a blank line after this
+
+" #t ())
+
+ ;; I think this file will be constructed wrong (gpg 0.9.3) but it
+ ;; should verify okay anyway.
+ ("this is a sig test
+ " #f ())
+
+ ;; check our special diff mode
+ ("--- mainproc.c Tue Jun 27 09:28:11 2000
++++ mainproc.c~ Thu Jun 8 22:50:25 2000
+@@ -1190,16 +1190,13 @@
+ md_enable( c->mfx.md, n1->pkt->pkt.signature->digest_algo);
+ }
+ /* ask for file and hash it */
+- if( c->sigs_only ) {
++ if( c->sigs_only )
+ rc = hash_datafiles( c->mfx.md, NULL,
+ c->signed_data, c->sigfilename,
+ n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 );
+" #t (--not-dash-escaped))))
+
+(let ((counter (make-counter)))
+ (for-each-p'
+ "Checking signing and verifying test vectors"
+ (lambda (vec)
+ (lettmp (tmp)
+ (with-output-to-file tmp (lambda () (display (:string vec))))
+ ((if (:check-equality vec) check-identity check-execution)
+ tmp
+ (check-signing `(--passphrase-fd "0" --clear-sign ,@(:options vec))
+ usrpass1))))
+ (lambda (vec) (counter))
+ vectors))
diff --git a/tests/openpgp/compression.scm b/tests/openpgp/compression.scm
new file mode 100755
index 0000000..d2e46cc
--- /dev/null
+++ b/tests/openpgp/compression.scm
@@ -0,0 +1,36 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(for-each-p
+ "Checking encryption using a specific compression algorithm"
+ (lambda (compression)
+ (for-each-p
+ ""
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg "" `(--yes --encrypt --recipient ,usrname2
+ --compress-algo ,compression))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity source)))
+ (append plain-files data-files)))
+ (force all-compression-algos))
diff --git a/tests/openpgp/conventional-mdc.scm b/tests/openpgp/conventional-mdc.scm
new file mode 100755
index 0000000..bb8327a
--- /dev/null
+++ b/tests/openpgp/conventional-mdc.scm
@@ -0,0 +1,50 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(define s2k '--s2k-count=65536)
+(define passphrase "Hier spricht HAL")
+
+(for-each-p
+ "Checking conventional encryption with MDC"
+ (lambda (algo)
+ (for-each-p
+ ""
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg passphrase `(--yes --passphrase-fd "0" ,s2k
+ --force-mdc -c
+ --cipher-algo ,algo))
+ (tr:gpg passphrase `(--yes --passphrase-fd "0" --decrypt ,s2k))
+ (tr:assert-identity source)))
+ '("plain-1" "data-80000")))
+ (force all-cipher-algos))
+
+(for-each-p
+ "Checking sign+symencrypt"
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg passphrase `(--yes --passphrase-fd "0" ,s2k -cs))
+ (tr:gpg passphrase `(--yes --passphrase-fd "0" --decrypt ,s2k))
+ (tr:assert-identity source)))
+ (append plain-files data-files))
diff --git a/tests/openpgp/conventional.scm b/tests/openpgp/conventional.scm
new file mode 100755
index 0000000..c480400
--- /dev/null
+++ b/tests/openpgp/conventional.scm
@@ -0,0 +1,49 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(define s2k '--s2k-count=65536)
+(define passphrase "Hier spricht HAL")
+
+(for-each-p
+ "Checking conventional encryption"
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg passphrase `(--yes --passphrase-fd "0" ,s2k -c))
+ (tr:gpg passphrase `(--yes --passphrase-fd "0" --decrypt ,s2k))
+ (tr:assert-identity source)))
+ '("plain-2" "data-32000"))
+
+(for-each-p
+ "Checking conventional encryption using a specific cipher"
+ (lambda (algo)
+ (for-each-p
+ ""
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg passphrase `(--yes --passphrase-fd "0" ,s2k -c
+ --cipher-algo ,algo))
+ (tr:gpg passphrase `(--yes --passphrase-fd "0" --decrypt ,s2k))
+ (tr:assert-identity source)))
+ '("plain-1" "data-80000")))
+ (force all-cipher-algos))
diff --git a/tests/openpgp/decrypt-dsa.scm b/tests/openpgp/decrypt-dsa.scm
new file mode 100755
index 0000000..9f39732
--- /dev/null
+++ b/tests/openpgp/decrypt-dsa.scm
@@ -0,0 +1,30 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(for-each-p
+ "Checking decryption of supplied DSA encrypted file"
+ (lambda (name)
+ (tr:do
+ (tr:open (in-srcdir "tests" "openpgp" (string-append name "-pgp.asc")))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity name)))
+ (list (car plain-files)))
diff --git a/tests/openpgp/decrypt-multifile.scm b/tests/openpgp/decrypt-multifile.scm
new file mode 100755
index 0000000..304ca49
--- /dev/null
+++ b/tests/openpgp/decrypt-multifile.scm
@@ -0,0 +1,47 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(info "Checking decryption of supplied files using --multifile.")
+
+(define my-wd (getcwd))
+(define encrypted-files (map (lambda (name)
+ (string-append name ".asc"))
+ plain-files))
+
+(with-temporary-working-directory
+ ;; First, copy the files so that GnuPG writes the decrypted files here
+ ;; and not into the source directory.
+ (for-each (lambda (name)
+ (file-copy (in-srcdir "tests" "openpgp" name) name))
+ encrypted-files)
+
+ ;; Now decrypt all files.
+ (call-check `(,@gpg --decrypt --multifile ,@encrypted-files))
+
+ ;; And verify the result. Reference files are in our original
+ ;; working directory courtesy of setup-legacy-environment.
+ (for-each-p
+ "Verifying files:"
+ (lambda (name)
+ (unless (file=? (path-join my-wd name) name)
+ (fail "decrypted file differs")))
+ plain-files))
diff --git a/tests/openpgp/decrypt-session-key.scm b/tests/openpgp/decrypt-session-key.scm
new file mode 100755
index 0000000..c3294e0
--- /dev/null
+++ b/tests/openpgp/decrypt-session-key.scm
@@ -0,0 +1,45 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2017 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(define (get-session-key filename)
+ (lettmp (sink)
+ (let* ((status' (call-popen `(,@gpg --status-fd=1 --decrypt
+ --show-session-key
+ --output ,sink ,filename) ""))
+ (status (map (lambda (l)
+ (assert (string-prefix? l "[GNUPG:] "))
+ (string-splitp (substring l 9 (string-length l))
+ char-whitespace? -1))
+ (string-split-newlines status'))))
+ (cadr (assoc "SESSION_KEY" status)))))
+
+(for-each-p
+ "Checking decryption of supplied files using the session key."
+ (lambda (name)
+ (let* ((source (in-srcdir "tests" "openpgp" (string-append name ".asc")))
+ (key (get-session-key source)))
+ (with-ephemeral-home-directory setup-environment-no-atexit stop-agent
+ (tr:do
+ (tr:open source)
+ (tr:gpg "" `(--yes --decrypt --override-session-key ,key))
+ (tr:assert-identity name)))))
+ plain-files)
diff --git a/tests/openpgp/decrypt-unwrap-verify.scm b/tests/openpgp/decrypt-unwrap-verify.scm
new file mode 100755
index 0000000..addc2da
--- /dev/null
+++ b/tests/openpgp/decrypt-unwrap-verify.scm
@@ -0,0 +1,41 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2017 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(lettmp (steve's-key)
+ (call-check `(,@gpg --output ,steve's-key --export "1D777619BE310D79"))
+
+ (for-each-p
+ "Checking unwrapping the encryption."
+ (lambda (name)
+ ;; First, unwrap the encrypted message using Steve's secret key.
+ (lettmp (unwrapped)
+ (tr:do
+ (tr:open (in-srcdir "tests" "openpgp" "samplemsgs" (string-append name ".asc")))
+ (tr:gpg "" `(--yes --decrypt --unwrap))
+ (tr:write-to unwrapped))
+
+ ;; Then, verify the signature with a clean working directory
+ ;; containing only Steve's public key.
+ (with-ephemeral-home-directory setup-environment-no-atexit stop-agent
+ (call-check `(,@gpg --import ,steve's-key))
+ (call-check `(,@gpg --verify ,unwrapped)))))
+ '("encsig-2-keys-3" "encsig-2-keys-4")))
diff --git a/tests/openpgp/decrypt.scm b/tests/openpgp/decrypt.scm
new file mode 100755
index 0000000..aae4c96
--- /dev/null
+++ b/tests/openpgp/decrypt.scm
@@ -0,0 +1,30 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(for-each-p
+ "Checking decryption of supplied files"
+ (lambda (name)
+ (tr:do
+ (tr:open (in-srcdir "tests" "openpgp" (string-append name ".asc")))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity name)))
+ plain-files)
diff --git a/tests/openpgp/default-key.scm b/tests/openpgp/default-key.scm
new file mode 100755
index 0000000..3580cad
--- /dev/null
+++ b/tests/openpgp/default-key.scm
@@ -0,0 +1,77 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+;; Import the sample key
+;;
+;; pub 1024R/8BC90111 2015-12-02
+;; Key fingerprint = E657 FB60 7BB4 F21C 90BB 6651 BC06 7AF2 8BC9 0111
+;; uid [ultimate] Barrett Brown <barrett@example.org>
+;; sub 1024R/3E880CFF 2015-12-02 (encryption)
+;; sub 1024R/F5F77B83 2015-12-02 (signing)
+;; sub 1024R/45117079 2015-12-02 (encryption)
+;; sub 1024R/1EA97479 2015-12-02 (signing)
+
+(info "Importing public key.")
+(call-check
+ `(,(tool 'gpg) --import
+ ,(in-srcdir "tests" "openpgp" "samplekeys/E657FB607BB4F21C90BB6651BC067AF28BC90111.asc")))
+
+;; By default, the most recent, valid signing subkey (1EA97479).
+(for-each-p
+ "Checking that the most recent, valid signing subkey is used by default"
+ (lambda (keyid)
+ (tr:do
+ (tr:pipe-do
+ (pipe:defer (lambda (sink) (display "" (fdopen sink "w"))))
+ (pipe:gpg `(--default-key ,keyid -s))
+ (pipe:gpg '(--verify --status-fd=1)))
+ (tr:call-with-content
+ (lambda (c)
+ (unless (string-contains?
+ c "VALIDSIG 5FBA84ACE02DCB17DA3DFF6BBCA43C441EA97479")
+ (exit 1))))))
+ '("8BC90111" "3E880CFF" "F5F77B83" "45117079" "1EA97479"))
+
+;; But, if we request a particular signing key, we should get it.
+(for-each-p
+ "Checking that the most recent, valid encryption subkey is used by default"
+ (lambda (keyid)
+ (tr:do
+ (tr:pipe-do
+ (pipe:defer (lambda (sink) (display "" (fdopen sink "w"))))
+ ;; We need another recipient, because --encrypt-to-default-key is
+ ;; not considered a recipient and gpg doesn't encrypt without any
+ ;; recipients.
+ ;;
+ ;; Note: it doesn't matter whether we specify the primary key or
+ ;; a subkey: the newest encryption subkey will be used.
+ (pipe:gpg `(--default-key ,keyid --encrypt-to-default-key
+ -r "439F02CA" -e))
+ (pipe:gpg '(--list-packets)))
+ (tr:call-with-content
+ (lambda (c)
+ (unless (any (lambda (line)
+ (and (string-prefix? line ":pubkey enc packet:")
+ (string-suffix? line "45117079")))
+ (string-split-newlines c))
+ (exit 1))))))
+ '("8BC90111" "3E880CFF" "F5F77B83" "45117079" "1EA97479"))
diff --git a/tests/openpgp/defs.scm b/tests/openpgp/defs.scm
new file mode 100644
index 0000000..b864005
--- /dev/null
+++ b/tests/openpgp/defs.scm
@@ -0,0 +1,509 @@
+;; Common definitions for the OpenPGP test scripts.
+;;
+;; Copyright (C) 2016, 2017 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+;;
+;; Constants.
+;;
+
+(define usrname1 "one@example.com")
+(define usrpass1 "def")
+(define usrname2 "two@example.com")
+(define usrpass2 "")
+(define usrname3 "three@example.com")
+(define usrpass3 "")
+
+(define dsa-usrname1 "pgp5")
+;; we use the sub key because we do not yet have the logic to derive
+;; the first encryption key from a keyblock (I guess) (Well of course
+;; we have this by now and the notation below will lookup the primary
+;; first and then search for the encryption subkey.)
+(define dsa-usrname2 "0xCB879DE9")
+
+(define keys
+ (package
+ (define (new fpr grip uids subkeys)
+ (package))
+ (define (subkey fpr grip)
+ (package))
+ (define alfa (new "A0FF4590BB6122EDEF6E3C542D727CC768697734"
+ "76F7E2B35832976B50A27A282D9B87E44577EB66"
+ '("alfa@example.net" "alpha@example.net")
+ (list
+ (subkey "3B3FBC948FE59301ED629EFB6AE6D7EE46A871F8"
+ "A0747D5F9425E6664F4FFBEED20FBCA79FDED2BD"))))
+ (define one (new "289B0EF1D105E124B6F626020EF77096D74C5F22"
+ "50B2D4FA4122C212611048BC5FC31BD44393626E"
+ '("one@example.com")
+ (list
+ (subkey "EB467DCA4AD7676A6A62B2ABABAB28A247BE2775"
+ "7E201E28B6FEB2927B321F443205F4724EBE637E"))))
+ (define two (new "C1DEBB34EA8B71009EAFA474973D50E1C40FDECF"
+ "343D8AF79796EE107D645A2787A9D9252F924E6F"
+ '("two@example.com")
+ (list
+ (subkey "CD3D0F5701CBFCACB2A4907305A37887B27907AA"
+ "8B5ABF3EF9EB8D96B91A0B8C2C4401C91C834C34"))))))
+
+(define key-file1 "samplekeys/rsa-rsa-sample-1.asc")
+(define key-file2 "samplekeys/ed25519-cv25519-sample-1.asc")
+
+(define plain-files '("plain-1" "plain-2" "plain-3" "plain-large"))
+(define data-files '("data-500" "data-9000" "data-32000" "data-80000"))
+(define exp-files '())
+(define all-files (append plain-files data-files))
+
+(let ((verbose (string->number (getenv "verbose"))))
+ (if (number? verbose)
+ (*set-verbose!* verbose)))
+
+(define (qualify executable)
+ (string-append executable (getenv "EXEEXT")))
+
+(define (getenv' key default)
+ (let ((value (getenv key)))
+ (if (string=? "" value)
+ default
+ value)))
+
+(define (percent-decode s)
+ (define (decode c)
+ (if (and (> (length c) 2) (char=? #\% (car c)))
+ (integer->char (string->number (string #\# #\x (cadr c) (caddr c))))
+ #f))
+ (let loop ((i 0) (c (string->list s)) (r (make-string (string-length s))))
+ (if (null? c)
+ (substring r 0 i)
+ (let ((decoded (decode c)))
+ (string-set! r i (if decoded decoded (car c)))
+ (loop (+ 1 i) (if decoded (cdddr c) (cdr c)) r)))))
+(assert (equal? (percent-decode "") ""))
+(assert (equal? (percent-decode "%61") "a"))
+(assert (equal? (percent-decode "foob%61r") "foobar"))
+
+(define (percent-encode s)
+ (define (encode c)
+ `(#\% ,@(string->list (number->string (char->integer c) 16))))
+ (let loop ((acc '()) (cs (reverse (string->list s))))
+ (if (null? cs)
+ (list->string acc)
+ (case (car cs)
+ ((#\: #\%)
+ (loop (append (encode (car cs)) acc) (cdr cs)))
+ (else
+ (loop (cons (car cs) acc) (cdr cs)))))))
+(assert (equal? (percent-encode "") ""))
+(assert (equal? (percent-encode "%61") "%2561"))
+(assert (equal? (percent-encode "foob%61r") "foob%2561r"))
+
+(define tools
+ '((gpgv "GPGV" "g10/gpgv")
+ (gpg-connect-agent "GPG_CONNECT_AGENT" "tools/gpg-connect-agent")
+ (gpgconf "GPGCONF" "tools/gpgconf")
+ (gpg-preset-passphrase "GPG_PRESET_PASSPHRASE"
+ "agent/gpg-preset-passphrase")
+ (gpgtar "GPGTAR" "tools/gpgtar")
+ (gpg-zip "GPGZIP" "tools/gpg-zip")
+ (pinentry "PINENTRY" "tests/openpgp/fake-pinentry")))
+
+(define bin-prefix (getenv "BIN_PREFIX"))
+(define installed? (not (string=? "" bin-prefix)))
+(define with-valgrind? (not (string=? (getenv "with_valgrind") "")))
+
+(define (tool-hardcoded which)
+ (let ((t (assoc which tools)))
+ (getenv' (cadr t)
+ (qualify (if installed?
+ (string-append bin-prefix "/" (basename (caddr t)))
+ (string-append (getenv "objdir") "/" (caddr t)))))))
+
+;; You can splice VALGRIND into your argument vector to run programs
+;; under valgrind. For example, to run valgrind on gpg, you may want
+;; to redefine gpg:
+;;
+;; (set! gpg `(,@valgrind ,@gpg))
+;;
+(define valgrind
+ '("/usr/bin/valgrind" -q --leak-check=no --track-origins=yes
+ --error-exitcode=154 --exit-on-first-error=yes))
+
+(unless installed?
+ (setenv "GNUPG_BUILDDIR" (getenv "objdir") #t))
+
+(define (gpg-conf . args)
+ (gpg-conf' "" args))
+(define (gpg-conf' input args)
+ (let ((s (call-popen `(,(tool-hardcoded 'gpgconf)
+ ,@(if installed? '()
+ (list '--build-prefix (getenv "objdir")))
+ ,@args) input)))
+ (map (lambda (line) (map percent-decode (string-split line #\:)))
+ (string-split-newlines s))))
+(define :gc:c:name car)
+(define :gc:c:description cadr)
+(define :gc:c:pgmname caddr)
+(define (:gc:o:name x) (list-ref x 0))
+(define (:gc:o:flags x) (string->number (list-ref x 1)))
+(define (:gc:o:level x) (string->number (list-ref x 2)))
+(define (:gc:o:description x) (list-ref x 3))
+(define (:gc:o:type x) (string->number (list-ref x 4)))
+(define (:gc:o:alternate-type x) (string->number (list-ref x 5)))
+(define (:gc:o:argument-name x) (list-ref x 6))
+(define (:gc:o:default-value x) (list-ref x 7))
+(define (:gc:o:default-argument x) (list-ref x 8))
+(define (:gc:o:value x) (if (< (length x) 10) "" (list-ref x 9)))
+
+(define (gpg-config component key)
+ (package
+ (define (value)
+ (let* ((conf (assoc key (gpg-conf '--list-options component)))
+ (type (:gc:o:type conf))
+ (value (:gc:o:value conf)))
+ (case type
+ ((0 2 3) (string->number value))
+ ((1 32) (substring value 1 (string-length value))))))
+ (define (update value)
+ (let ((value' (cond
+ ((string? value) (string-append "\"" value))
+ ((number? value) (number->string value))
+ (else (throw "Unsupported value" value)))))
+ (gpg-conf' (string-append key ":0:" (percent-encode value'))
+ `(--change-options ,component))))
+ (define (clear)
+ (gpg-conf' (string-append key ":16:")
+ `(--change-options ,component)))))
+
+(define gpg-components (apply gpg-conf '(--list-components)))
+
+(define (tool which)
+ (case which
+ ((gpg gpg-agent scdaemon gpgsm dirmngr)
+ (:gc:c:pgmname (assoc (symbol->string which) gpg-components)))
+ (else
+ (tool-hardcoded which))))
+
+(define (gpg-has-option? option)
+ (string-contains? (call-popen `(,(tool 'gpg) --dump-options) "")
+ option))
+
+(define have-opt-always-trust
+ (catch #f
+ (with-ephemeral-home-directory (lambda ()) (lambda ())
+ (call-check `(,(tool 'gpg) --gpgconf-test --always-trust)))
+ #t))
+
+(define GPG `(,(tool 'gpg) --no-permission-warning
+ ,@(if have-opt-always-trust '(--always-trust) '())))
+(define GPGV `(,(tool 'gpgv)))
+(define PINENTRY (tool 'pinentry))
+
+(define (tr:gpg input args)
+ (tr:spawn input `(,@GPG --output **out** ,@args **in**)))
+
+(define (pipe:gpg args)
+ (pipe:spawn `(,@GPG --output - ,@args -)))
+
+(define (gpg-with-colons args)
+ (let ((s (call-popen `(,@GPG --with-colons ,@args) "")))
+ (map (lambda (line) (string-split line #\:))
+ (string-split-newlines s))))
+
+;; Convenient accessors for the colon output.
+(define (:type x) (string->symbol (list-ref x 0)))
+(define (:length x) (string->number (list-ref x 2)))
+(define (:alg x) (string->number (list-ref x 3)))
+(define (:expire x) (list-ref x 6))
+(define (:fpr x) (list-ref x 9))
+(define (:cap x) (list-ref x 11))
+
+(define (have-public-key? key)
+ (catch #f
+ (pair? (filter (lambda (l) (and (equal? 'fpr (:type l))
+ (equal? key::fpr (:fpr l))))
+ (gpg-with-colons `(--list-keys ,key::fpr))))))
+
+(define (have-secret-key? key)
+ (catch #f
+ (pair? (filter (lambda (l) (and (equal? 'fpr (:type l))
+ (equal? key::fpr (:fpr l))))
+ (gpg-with-colons `(--list-secret-keys ,key::fpr))))))
+
+(define (have-secret-key-file? key)
+ (file-exists? (path-join (getenv "GNUPGHOME") "private-keys-v1.d"
+ (string-append key::grip ".key"))))
+
+(define (get-config what)
+ (string-split (caddar (gpg-with-colons `(--list-config ,what))) #\;))
+
+(define all-pubkey-algos (delay (get-config "pubkeyname")))
+(define all-hash-algos (delay (get-config "digestname")))
+(define all-cipher-algos (delay (get-config "ciphername")))
+(define all-compression-algos (delay (get-config "compressname")))
+
+(define (have-pubkey-algo? x)
+ (not (not (member x (force all-pubkey-algos)))))
+(define (have-hash-algo? x)
+ (not (not (member x (force all-hash-algos)))))
+(define (have-cipher-algo? x)
+ (not (not (member x (force all-cipher-algos)))))
+(define (have-compression-algo? x)
+ (not (not (member x (force all-compression-algos)))))
+
+(define (gpg-pipe args0 args1 errfd)
+ (lambda (source sink)
+ (let* ((p (pipe))
+ (task0 (spawn-process-fd `(,@GPG ,@args0)
+ source (:write-end p) errfd))
+ (_ (close (:write-end p)))
+ (task1 (spawn-process-fd `(,@GPG ,@args1)
+ (:read-end p) sink errfd)))
+ (close (:read-end p))
+ (wait-processes (list GPG GPG) (list task0 task1) #t))))
+
+(setenv "GPG_AGENT_INFO" "" #t)
+(setenv "GNUPGHOME" (getcwd) #t)
+(define GNUPGHOME (getcwd))
+
+;;
+;; GnuPG helper.
+;;
+
+;; Call GPG to obtain the hash sums. Either specify an input file in
+;; ARGS, or an string in INPUT. Returns a list of (<algo>
+;; "<hashsum>") lists.
+(define (gpg-hash-string args input)
+ (map
+ (lambda (line)
+ (let ((p (string-split line #\:)))
+ (list (string->number (cadr p)) (caddr p))))
+ (string-split-newlines
+ (call-popen `(,@GPG --with-colons ,@args) input))))
+
+;; Dearmor a file.
+(define (dearmor source-name sink-name)
+ (pipe:do
+ (pipe:open source-name (logior O_RDONLY O_BINARY))
+ (pipe:spawn `(,@GPG --dearmor))
+ (pipe:write-to sink-name (logior O_WRONLY O_CREAT O_BINARY) #o600)))
+
+(define (gpg-dump-packets source-name sink-name)
+ (pipe:do
+ (pipe:open source-name (logior O_RDONLY O_BINARY))
+ (pipe:spawn `(,@GPG --list-packets))
+ (pipe:write-to sink-name (logior O_WRONLY O_CREAT O_BINARY) #o600)))
+
+;;
+;; Support for test environment creation and teardown.
+;;
+
+(define (make-test-data filename size)
+ (call-with-binary-output-file
+ filename
+ (lambda (port)
+ (display (make-random-string size) port))))
+
+(define (create-file name . lines)
+ (catch #f (unlink name))
+ (letfd ((fd (open name (logior O_WRONLY O_CREAT O_BINARY) #o600)))
+ (let ((port (fdopen fd "wb")))
+ (for-each (lambda (line) (display line port) (newline port))
+ lines))))
+
+(define (create-gpghome)
+ (log "Creating test environment...")
+
+ (srandom (getpid))
+ (make-test-data "random_seed" 600)
+
+ (log "Creating configuration files")
+
+ (if (flag "--use-keyring" *args*)
+ (create-file "pubring.gpg"))
+
+ (create-file "gpg.conf"
+ "no-greeting"
+ "no-secmem-warning"
+ "no-permission-warning"
+ "batch"
+ "no-auto-key-retrieve"
+ "no-auto-key-locate"
+ "allow-weak-digest-algos"
+ "allow-weak-key-signatures"
+ "ignore-mdc-error"
+ (if have-opt-always-trust
+ "no-auto-check-trustdb" "#no-auto-check-trustdb")
+ (string-append "agent-program "
+ (tool 'gpg-agent)
+ "|--debug-quick-random\n")
+ )
+ (create-file "gpg-agent.conf"
+ "allow-preset-passphrase"
+ "no-grab"
+ "enable-ssh-support"
+ (if (flag "--extended-key-format" *args*)
+ "enable-extended-key-format" "#enable-extended-key-format")
+ (string-append "pinentry-program " (tool 'pinentry))
+ "disable-scdaemon"))
+
+;; Initialize the test environment, install appropriate configuration
+;; and start the agent, without any keys.
+(define (setup-environment)
+ (create-gpghome)
+ (start-agent))
+
+(define (setup-environment-no-atexit)
+ (create-gpghome)
+ (start-agent #t))
+
+(define (create-sample-files)
+ (log "Creating sample data files")
+ (for-each
+ (lambda (size)
+ (make-test-data (string-append "data-" (number->string size))
+ size))
+ '(500 9000 32000 80000))
+
+ (log "Unpacking samples")
+ (for-each
+ (lambda (name)
+ (dearmor (in-srcdir "tests" "openpgp" (string-append name "o.asc")) name))
+ plain-files))
+
+(define (create-legacy-gpghome)
+ (create-sample-files)
+
+ (log "Storing private keys")
+ (for-each
+ (lambda (name)
+ (dearmor (in-srcdir "tests" "openpgp" "privkeys" (string-append name ".asc"))
+ (string-append "private-keys-v1.d/" name ".key")))
+ '("50B2D4FA4122C212611048BC5FC31BD44393626E"
+ "7E201E28B6FEB2927B321F443205F4724EBE637E"
+ "13FDB8809B17C5547779F9D205C45F47CE0217CE"
+ "343D8AF79796EE107D645A2787A9D9252F924E6F"
+ "8B5ABF3EF9EB8D96B91A0B8C2C4401C91C834C34"
+ "0D6F6AD4C4C803B25470F9104E9F4E6A4CA64255"
+ "FD692BD59D6640A84C8422573D469F84F3B98E53"
+ "76F7E2B35832976B50A27A282D9B87E44577EB66"
+ "A0747D5F9425E6664F4FFBEED20FBCA79FDED2BD"
+ "00FE67F28A52A8AA08FFAED20AF832DA916D1985"
+ "1DF48228FEFF3EC2481B106E0ACA8C465C662CC5"
+ "A2832820DC9F40751BDCD375BB0945BA33EC6B4C"
+ "ADE710D74409777B7729A7653373D820F67892E0"
+ "CEFC51AF91F68A2904FBFF62C4F075A4785B803F"
+ "1E28F20E41B54C2D1234D896096495FF57E08D18"
+ "EB33B687EB8581AB64D04852A54453E85F3DF62D"
+ "C6A6390E9388CDBAD71EAEA698233FE5E04F001E"
+ "D69102E0F5AC6B6DB8E4D16DA8E18CF46D88CAE3"))
+
+ (log "Importing public demo and test keys")
+ (for-each
+ (lambda (file)
+ (call-check `(,@GPG --yes --import ,(in-srcdir "tests" "openpgp" file))))
+ (list "pubdemo.asc" "pubring.asc" key-file1))
+
+ (pipe:do
+ (pipe:open (in-srcdir "tests" "openpgp" "pubring.pkr.asc") (logior O_RDONLY O_BINARY))
+ (pipe:spawn `(,@GPG --dearmor))
+ (pipe:spawn `(,@GPG --yes --import))))
+
+(define (preset-passphrases)
+ (log "Presetting passphrases")
+ ;; one@example.com
+ (call-check `(,(tool 'gpg-preset-passphrase)
+ --preset --passphrase def
+ "50B2D4FA4122C212611048BC5FC31BD44393626E"))
+ (call-check `(,(tool 'gpg-preset-passphrase)
+ --preset --passphrase def
+ "7E201E28B6FEB2927B321F443205F4724EBE637E"))
+ ;; alpha@example.net
+ (call-check `(,(tool 'gpg-preset-passphrase)
+ --preset --passphrase abc
+ "76F7E2B35832976B50A27A282D9B87E44577EB66"))
+ (call-check `(,(tool 'gpg-preset-passphrase)
+ --preset --passphrase abc
+ "A0747D5F9425E6664F4FFBEED20FBCA79FDED2BD")))
+
+;; Initialize the test environment, install appropriate configuration
+;; and start the agent, with the keys from the legacy test suite.
+(define (setup-legacy-environment)
+ (create-gpghome)
+ (if (member "--unpack-tarball" *args*)
+ (begin
+ (call-check `(,(tool 'gpgtar) --extract --directory=. ,(cadr *args*)))
+ (start-agent))
+ (begin
+ (start-agent)
+ (create-legacy-gpghome)))
+ (preset-passphrases))
+
+;; Create the socket dir and start the agent.
+(define (start-agent . args)
+ (log "Starting gpg-agent...")
+ (let ((gnupghome (getenv "GNUPGHOME")))
+ (if (null? args)
+ (atexit (lambda ()
+ (with-home-directory gnupghome (stop-agent))))))
+ (catch (log "Warning: Creating socket directory failed:" (car *error*))
+ (gpg-conf '--create-socketdir))
+ (call-check `(,(tool 'gpg-connect-agent) --verbose
+ ,(string-append "--agent-program=" (tool 'gpg-agent)
+ "|--debug-quick-random")
+ /bye)))
+
+;; Stop the agent and other daemons and remove the socket dir.
+(define (stop-agent)
+ (log "Stopping gpg-agent...")
+ (gpg-conf '--kill 'all)
+ (catch (log "Warning: Removing socket directory failed.")
+ (gpg-conf '--remove-socketdir)))
+
+;; Get the trust level for KEYID. Any remaining arguments are simply
+;; passed to GPG.
+;;
+;; This function only supports keys with a single user id.
+(define (gettrust keyid . args)
+ (let ((trust
+ (list-ref (assoc "pub" (gpg-with-colons
+ `(,@args
+ --list-keys ,keyid))) 1)))
+ (unless (and (= 1 (string-length trust))
+ (member (string-ref trust 0) (string->list "oidreqnmfuws-")))
+ (fail "Bad trust value:" trust))
+ trust))
+
+;; Check that KEYID's trust level matches EXPECTED-TRUST. Any
+;; remaining arguments are simply passed to GPG.
+;;
+;; This function only supports keys with a single user id.
+(define (checktrust keyid expected-trust . args)
+ (let ((trust (apply gettrust `(,keyid ,@args))))
+ (unless (string=? trust expected-trust)
+ (fail keyid ": Expected trust to be" expected-trust
+ "but got" trust))))
+
+
+;;
+;; Enable checking with valgrind if the envvar "with_valgrind" is set
+;;
+(when with-valgrind?
+ (set! gpg `(,@valgrind ,@gpg)))
+
+
+
+;; end
diff --git a/tests/openpgp/delete-keys.scm b/tests/openpgp/delete-keys.scm
new file mode 100755
index 0000000..16bde5f
--- /dev/null
+++ b/tests/openpgp/delete-keys.scm
@@ -0,0 +1,109 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(let* ((key keys::alfa)
+ (subkey (car key::subkeys)))
+ (assert (have-public-key? key))
+ (assert (have-public-key? subkey))
+ (assert (have-secret-key? key))
+ (assert (have-secret-key-file? key))
+ (assert (have-secret-key? subkey))
+ (assert (have-secret-key-file? subkey))
+
+ ;; Firstly, delete the secret key.
+ (call-check `(,@gpg --delete-secret-keys ,key::fpr))
+ (assert (have-public-key? key))
+ (assert (have-public-key? subkey))
+ (assert (not (have-secret-key? key)))
+ (assert (not (have-secret-key-file? key)))
+ (assert (not (have-secret-key? subkey)))
+ (assert (not (have-secret-key-file? subkey)))
+
+ ;; Now, delete the public key.
+ (call-check `(,@gpg --delete-keys ,key::fpr))
+ (assert (not (have-public-key? key)))
+ (assert (not (have-public-key? subkey))))
+
+;; Do the same for key one, but do the subkeys separately.
+(let* ((key keys::one)
+ (subkey (car key::subkeys)))
+ (assert (have-public-key? key))
+ (assert (have-public-key? subkey))
+ (assert (have-secret-key? key))
+ (assert (have-secret-key-file? key))
+ (assert (have-secret-key-file? key))
+ (assert (have-secret-key? subkey))
+ (assert (have-secret-key-file? subkey))
+
+ ;; Firstly, delete the secret subkey.
+ (call-check `(,@gpg --delete-secret-keys ,subkey::fpr))
+ (assert (have-public-key? key))
+ (assert (have-public-key? subkey))
+ ;; JW: Deleting the secret subkey also deletes the secret key. This
+ ;; is a deliberate design choice, and currently there is no way to
+ ;; delete the subkey without using --edit-key.
+ ;; XXX (assert (have-secret-key? key))
+ ;; XXX (assert (have-secret-key-file? key))
+ (assert (not (have-secret-key? subkey)))
+ (assert (not (have-secret-key-file? subkey)))
+
+ ;; Then, delete the secret key.
+ ;; JW: We already deleted the key. See above.
+ ;; XXX (call-check `(,@gpg --delete-secret-keys ,key::fpr))
+ (assert (have-public-key? key))
+ (assert (have-public-key? subkey))
+ (assert (not (have-secret-key? key)))
+ (assert (not (have-secret-key-file? key)))
+ (assert (not (have-secret-key? subkey)))
+ (assert (not (have-secret-key-file? subkey)))
+
+ ;; Now, delete the public subkey.
+ (call-check `(,@gpg --delete-keys ,subkey::fpr))
+ ;; JW: Deleting the subkey also deletes the key. This
+ ;; is a deliberate design choice, and currently there is no way to
+ ;; delete the subkey without using --edit-key.
+ ;; XXX (assert (have-public-key? key))
+ (assert (not (have-public-key? subkey)))
+
+ ;; Now, delete the public key.
+ ;; JW: We already deleted the key. See above.
+ ;; XXX (call-check `(,@gpg --delete-keys ,key::fpr))
+ (assert (not (have-public-key? key)))
+ (assert (not (have-public-key? subkey))))
+
+(let* ((key keys::two)
+ (subkey (car key::subkeys)))
+ (assert (have-public-key? key))
+ (assert (have-public-key? subkey))
+ (assert (have-secret-key? key))
+ (assert (have-secret-key-file? key))
+ (assert (have-secret-key? subkey))
+ (assert (have-secret-key-file? subkey))
+
+ ;; Delete everything at once.
+ (call-check `(,@gpg --delete-secret-and-public-key ,key::fpr))
+ (assert (not (have-public-key? key)))
+ (assert (not (have-public-key? subkey)))
+ (assert (not (have-secret-key? key)))
+ (assert (not (have-secret-key-file? key)))
+ (assert (not (have-secret-key? subkey)))
+ (assert (not (have-secret-key-file? subkey))))
diff --git a/tests/openpgp/detach.scm b/tests/openpgp/detach.scm
new file mode 100755
index 0000000..12ed167
--- /dev/null
+++ b/tests/openpgp/detach.scm
@@ -0,0 +1,32 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(for-each-p
+ "Checking detached signatures"
+ (lambda (source)
+ (lettmp (tmp)
+ (call-popen `(,@GPG --yes --passphrase-fd "0" -sb
+ --output ,tmp ,source ) usrpass1)
+ (pipe:do
+ (pipe:open source (logior O_RDONLY O_BINARY))
+ (pipe:spawn `(,@GPG --yes --verify ,tmp -)))))
+ (append plain-files data-files))
diff --git a/tests/openpgp/detachm.scm b/tests/openpgp/detachm.scm
new file mode 100755
index 0000000..75faab7
--- /dev/null
+++ b/tests/openpgp/detachm.scm
@@ -0,0 +1,36 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(define files (append plain-files data-files))
+
+(info "Checking detached signatures of multiple files")
+(lettmp (tmp)
+ (call-popen `(,@GPG --yes --passphrase-fd "0" -sb
+ --output ,tmp ,@files) usrpass1)
+ (pipe:do
+ (pipe:defer (lambda (sink)
+ (for-each (lambda (file)
+ (pipe:do
+ (pipe:open file (logior O_RDONLY O_BINARY))
+ (pipe:splice sink)))
+ files)))
+ (pipe:spawn `(,@GPG --yes --verify ,tmp -))))
diff --git a/tests/openpgp/ecc.scm b/tests/openpgp/ecc.scm
new file mode 100755
index 0000000..a63ec45
--- /dev/null
+++ b/tests/openpgp/ecc.scm
@@ -0,0 +1,249 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(define keygrips '("8E06A180EFFE4C65B812150CAF19BF30C0689A4C"
+ "E4403F3FD7A443FAC29FEF288FA0D20AC212851E"
+ "0B7554421FFB14A06CB9F63FB49A85A58E97ABAC"
+ "303ACC892C2D786C8A789677C0BE54DA8538F903"
+ "9FE5C36985351524B6AFA19FDCBC1A3A750B6F5F"
+ "145A52CC7ED3FD41C5B0A26BE220FEED36AF24DE"))
+(define mainkeyids '("BAA59D9C" "0F54719F" "45AF2FFE"))
+
+(unless (have-pubkey-algo? "ECDH")
+ (skip "No ECC support due to an old Libgcrypt"))
+
+(info "Preparing for ECC test")
+(for-each
+ (lambda (grip)
+ (catch '() (unlink (string-append "private-keys-v1.d/" grip ".key")))
+ (call-check `(,(tool 'gpg-preset-passphrase)
+ --preset --passphrase ecc ,grip)))
+ keygrips)
+
+(info "Importing ECC public keys")
+(for-each
+ (lambda (keyid)
+ (call `(,(tool 'gpg) --delete-key --batch --yes ,keyid)))
+ mainkeyids)
+
+(for-each
+ (lambda (n)
+ (call-check `(,(tool 'gpg) --import
+ ,(in-srcdir "tests" "openpgp" (string-append
+ "samplekeys/ecc-sample-"
+ (number->string n)
+ "-pub.asc")))))
+ '(1 2 3))
+
+;; The following is an opaque ECDSA signature on a message "This is one
+;; line\n" (17 byte long) by the primary 256 bit key:
+(define msg_opaque_signed_256 "-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2.1.0-ecc (GNU/Linux)
+
+owGbwMvMwCHMvVT3w66lc+cwrlFK4k5N1k3KT6nUK6ko8Zl8MSEkI7NYAYjy81IV
+cjLzUrk64lgYhDkY2FiZQNIMXJwCMO31rxgZ+tW/zesUPxWzdKWrtLGW/LkP5rXL
+V/Yvnr/EKjBbQuvZSYa/klsum6XFmTze+maVgclT6Rc6hzqqxNy6o6qdTTmLJuvp
+AQA=
+=GDv4
+-----END PGP MESSAGE----")
+
+;; The following is an opaque ECDSA signature on a message "This is one
+;; line\n" (17 byte long) by the primary 384 bit key:
+(define msg_opaque_signed_384 "-----BEGIN PGP MESSAGE-----
+Version: PGP Command Line v10.0.0 (Linux)
+
+qANQR1DIqwE7wsvMwCnM2WDcwR9SOJ/xtFISd25qcXFieqpeSUUJAxCEZGQWKwBR
+fl6qQk5mXirXoXJmVgbfYC5xmC5hzsDPjHXqbDLzpXpTBXSZV3L6bAgP3Kq7Ykmo
+7Ds1v4UfBS+3CSSon7Pzq79WLjzXXEH54MkjPxnrw+8cfMVnY7Bi18J702Nnsa7a
+9lMv/PM0/ao9CZ3KX7Q+Tv1rllTZ5Hj4V1frw431QnHfAA==
+=elKT
+-----END PGP MESSAGE-----")
+
+;; The following is an opaque ECDSA signature on a message "This is one
+;; line\n" (17 byte long) by the primary 521 bit key:
+(define msg_opaque_signed_521 "-----BEGIN PGP MESSAGE-----
+Version: PGP Command Line v10.0.0 (Linux)
+
+qANQR1DIwA8BO8LLzMAlnO3Y8tB1vf4/xtNKSdy5qcXFiempeiUVJQxAEJKRWawA
+RPl5qQo5mXmpXIdmMLMy+AaLnoLpEubatpeJY2Lystd7Qt32q2UcvRS5kNPWtDB7
+ryufvcrWtFM7Jx8qXKDxZuqr7b9PGv1Ssk+I8TzB2O9dZC+n/jv+PAdbuu7mLe33
+Gf9pLd3weV3Qno6FOqxGa5ZszQx+uer2xH3/El9x/2pVeO4l15ScsL7qWMTmffmG
+Ic1RdzgeCfosMF+l/zVRchcLKzenEQA=
+=ATtX
+-----END PGP MESSAGE-----")
+
+(lettmp (z)
+ (letfd ((fd (open z (logior O_WRONLY O_CREAT O_BINARY) #o600)))
+ (display "This is one line\n" (fdopen fd "wb")))
+
+ (for-each-p
+ "Checking opaque ECDSA signatures"
+ (lambda (test)
+ (lettmp (x y)
+ (call-with-output-file
+ x (lambda (p) (display (eval test (current-environment)) p)))
+ (call-check `(,(tool 'gpg) --output ,y --verify ,x))
+ (unless (file=? y z) (fail "mismatch"))))
+ '(msg_opaque_signed_256 msg_opaque_signed_384 msg_opaque_signed_521)))
+
+;;
+;; Import the secret keys so that we now can sign and decrypt.
+;;
+;; Note that the PGP generated secret keys are not self-signed, thus we
+;; need to pass an appropriate option.
+;;
+(info "Importing ECC secret keys")
+(setenv "PINENTRY_USER_DATA" "ecc" #t)
+(for-each
+ (lambda (n)
+ (call-check `(,(tool 'gpg) --import
+ ,@(if (> n 1) '(--allow-non-selfsigned-uid) '())
+ ,(in-srcdir "tests" "openpgp" (string-append
+ "samplekeys/ecc-sample-"
+ (number->string n)
+ "-sec.asc")))))
+ '(1 2 3))
+
+;;
+;; Check a few sample encrtpted messages.
+;;
+(info "Checking ECC encryption")
+
+;; The following block encrypts the text "This is one line\n", 17 bytes,
+;; with the subkey 4089AB73.
+(define msg_encrypted_256 "-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2.1.0-ecc (GNU/Linux)
+
+hH4Dd863o0CJq3MSAgMEHdIYZQx+rV1cjy7qitIOEICFFzp4cjsRX4r+rDdMcQUs
+h7VZmbP1c9C0s9sgCKwubWfkcYUl2ZOju4gy+s4MYTBb4/j8JjnJ9Bqn6LWutTXJ
+zwsdP13VIJLnhiNqISdR3/6xWQ0ICRYzwb95nUZ1c1DSVgFpjPgUvi4pgYbTpcDB
+jzILKWBfBDT/jck169XE8vgtbcqVQYZ7lZpaY9CzEbC+4dXZmV1gm5MafpTyFWgH
+VnyrZB4gad9Lp9e0RKHHcOOE7s/NeLuu
+=odUZ
+-----END PGP MESSAGE-----")
+
+;; The following block encrypts the text "This is one line\n", 17 bytes,
+;; with the subkey 9A201946:
+(define msg_encrypted_384 "-----BEGIN PGP MESSAGE-----
+Version: PGP Command Line v10.0.0 (Linux)
+
+qANQR1DBngOqi5OPmiAZRhIDAwQqIr/00cJyf+QP+VA4QKVkk77KMHdz9OVaR2XK
+0VYu0F/HPm89vL2orfm2hrAZxY9G2R0PG4Wk5Lg04UjKca/O72uWtjdPYulFidmo
+uB0QpzXFz22ZZinxeVPLPEr19Pow0EwCc95cg4HAgrD0nV9vRcTJ/+juVfvsJhAO
+isMKqrFNMvwnK5A1ECeyVXe7oLZl0lUBRhLr59QTtvf85QJjg/m5kaGy8XCJvLv3
+61pZa6KUmw89PjtPak7ebcjnINL01vwmyeg1PAyW/xjeGGvcO+R4P1b4ewyFnJyR
+svzIJcP7d4DqYOw7
+=oiTJ
+-----END PGP MESSAGE-----")
+
+;; The following block encrypts the text "This is one line\n", 17 bytes,
+;; with the subkey A81C4838:
+(define msg_encrypted_521 "-----BEGIN PGP MESSAGE-----
+Version: PGP Command Line v10.0.0 (Linux)
+
+qANQR1DBwAIDB+qqSKgcSDgSBCMEAKpzTUxB4c56C7g09ekD9I+ttC5ER/xzDmXU
+OJmFqU5w3FllhFj4TgGxxdH+8fv4W2Ag0IKoJvIY9V1V7oUCClfqAR01QbN7jGH/
+I9GFFnH19AYEgMKgFmh14ZwN1BS6/VHh+H4apaYqapbx8/09EL+DV9zWLX4GRLXQ
+VqCR1N2rXE29MJFzGmDOCueQNkUjcbuenoCSKcNT+6xhO27U9IYVCg4BhRUDGfD6
+dhfRzBLxL+bKR9JVAe46+K8NLjRVu/bd4Iounx4UF5dBk8ERy+/8k9XantDoQgo6
+RPqCad4Dg/QqkpbK3y574ds3VFNJmc4dVpsXm7lGV5w0FBxhVNPoWNhhECMlTroX
+Rg==
+=5GqW
+-----END PGP MESSAGE-----")
+
+(lettmp (z)
+ (letfd ((fd (open z (logior O_WRONLY O_CREAT O_BINARY) #o600)))
+ (display "This is one line\n" (fdopen fd "wb")))
+
+ (for-each-p
+ "Checking ECDH decryption"
+ (lambda (test)
+ (lettmp (x y)
+ (call-with-output-file
+ x (lambda (p) (display (eval test (current-environment)) p)))
+ (call-check `(,@GPG --yes --output ,y --decrypt ,x))
+ (unless (file=? y z) (fail "mismatch"))))
+ '(msg_encrypted_256 msg_encrypted_384 msg_encrypted_521)))
+
+;;
+;; Now check that we can encrypt and decrypt our own messages.
+;;
+;; Note that we don't need to provide a passphrase because we already
+;; preset the passphrase into the gpg-agent.
+;;
+(for-each-p
+ "Checking ECC encryption and decryption"
+ (lambda (source)
+ (for-each-p
+ ""
+ (lambda (keyid)
+ (tr:do
+ (tr:open source)
+ (tr:gpg "" `(--yes --encrypt --recipient ,keyid))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity source)))
+ mainkeyids))
+ (append plain-files data-files))
+
+;;
+;; Now check that we can sign and verify our own messages.
+;;
+(for-each-p
+ "Checking ECC signing and verifiction"
+ (lambda (source)
+ (for-each-p
+ ""
+ (lambda (keyid)
+ (tr:do
+ (tr:open source)
+ (tr:gpg "" `(--yes --sign --local-user ,keyid))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity source)))
+ mainkeyids))
+ (append plain-files data-files))
+
+;;
+;; Let us also try to import the keys only from a secret keyblock.
+;;
+;; Because PGP does not sign the UID, it is not very useful to work
+;; with this key unless we go into the trouble of adding the
+;; self-signature.
+;;
+(info "Importing ECC secret keys directly")
+(for-each
+ (lambda (keyid)
+ (catch '() (unlink (string-append "private-keys-v1.d/" keyid ".key"))))
+ keygrips)
+(for-each
+ (lambda (keyid)
+ (call `(,(tool 'gpg) --delete-key --batch --yes ,keyid)))
+ mainkeyids)
+
+(for-each
+ (lambda (n)
+ (call-check `(,(tool 'gpg) --import
+ ,@(if (> n 1) '(--allow-non-selfsigned-uid) '())
+ ,(in-srcdir "tests" "openpgp" (string-append
+ "samplekeys/ecc-sample-"
+ (number->string n)
+ "-sec.asc")))))
+ '(1 2 3))
diff --git a/tests/openpgp/enarmor.scm b/tests/openpgp/enarmor.scm
new file mode 100755
index 0000000..1fe3256
--- /dev/null
+++ b/tests/openpgp/enarmor.scm
@@ -0,0 +1,31 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(for-each-p
+ "Checking armor encoding and decoding"
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg "" `(--enarmor))
+ (tr:gpg "" '(--dearmor))
+ (tr:assert-identity source)))
+ (append plain-files data-files))
diff --git a/tests/openpgp/encrypt-dsa.scm b/tests/openpgp/encrypt-dsa.scm
new file mode 100755
index 0000000..1658973
--- /dev/null
+++ b/tests/openpgp/encrypt-dsa.scm
@@ -0,0 +1,46 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(for-each-p
+ "Checking encryption using DSA"
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg "" `(--yes --encrypt --recipient ,dsa-usrname2))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity source)))
+ (append plain-files data-files))
+
+(for-each-p
+ "Checking encryption using DSA and a specific cipher algorithm"
+ (lambda (cipher)
+ (for-each-p
+ ""
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg "" `(--yes --encrypt --recipient ,dsa-usrname2
+ --cipher-algo ,cipher))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity source)))
+ (append plain-files data-files)))
+ (force all-cipher-algos))
diff --git a/tests/openpgp/encrypt-multifile.scm b/tests/openpgp/encrypt-multifile.scm
new file mode 100755
index 0000000..1b69ff5
--- /dev/null
+++ b/tests/openpgp/encrypt-multifile.scm
@@ -0,0 +1,39 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(define files (append plain-files data-files))
+
+(info "Checking encryption of supplied files using --multifile.")
+
+;; Now encrypt all files.
+(call-check `(,@gpg --encrypt --recipient ,usrname2
+ --multifile ,@files))
+
+;; And check if we can decrypt them.
+(for-each-p
+ "Verifying files:"
+ (lambda (source)
+ (tr:do
+ (tr:open (string-append source ".gpg"))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity source)))
+ files)
diff --git a/tests/openpgp/encrypt.scm b/tests/openpgp/encrypt.scm
new file mode 100755
index 0000000..f59a1f0
--- /dev/null
+++ b/tests/openpgp/encrypt.scm
@@ -0,0 +1,61 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(for-each-p
+ "Checking encryption"
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg "" `(--yes --encrypt --recipient ,usrname2))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity source)))
+ (append plain-files data-files))
+
+(for-each-p
+ "Checking encryption using a specific cipher algorithm"
+ (lambda (cipher)
+ (for-each-p
+ ""
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg "" `(--yes --encrypt --recipient ,usrname2
+ --cipher-algo ,cipher))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity source)))
+ (append plain-files data-files)))
+ (force all-cipher-algos))
+
+
+;; We encrypt to two keys and we have also put the first key into our
+;; pubring, so that decryption will work.
+(for-each-p
+ "Checking encryption using a key from file"
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg "" `(--yes -v --no-keyring --encrypt
+ --recipient-file ,(in-srcdir "tests" "openpgp" key-file1)
+ --hidden-recipient-file ,(in-srcdir "tests" "openpgp" key-file2)))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity source)))
+ plain-files)
diff --git a/tests/openpgp/encryptp.scm b/tests/openpgp/encryptp.scm
new file mode 100755
index 0000000..0f09a1e
--- /dev/null
+++ b/tests/openpgp/encryptp.scm
@@ -0,0 +1,32 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(for-each-p
+ "Checking encryption and decryption using pipes"
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:pipe-do
+ (pipe:gpg `(--yes --encrypt --recipient ,usrname2))
+ (pipe:gpg '(--yes --decrypt)))
+ (tr:assert-identity source)))
+ (append plain-files data-files))
diff --git a/tests/openpgp/export.scm b/tests/openpgp/export.scm
new file mode 100755
index 0000000..aa6fa78
--- /dev/null
+++ b/tests/openpgp/export.scm
@@ -0,0 +1,100 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(define (check-for predicate lines message)
+ (unless (any predicate lines)
+ (fail message)))
+
+(define (check-exported-key dump keyid)
+ (check-for (lambda (l)
+ (and (string-prefix? l " keyid: ")
+ (string-suffix? l keyid))) dump
+ "Keyid not found")
+ (check-for (lambda (l) (string-prefix? l ":user ID packet:")) dump
+ "User ID packet not found")
+ (check-for (lambda (l)
+ (and (string-prefix? l ":signature packet:")
+ (string-contains? l "keyid")
+ (string-suffix? l keyid))) dump
+ "Signature packet not found"))
+
+(define (check-exported-public-key packet-dump keyid)
+ (let ((dump (string-split-newlines packet-dump)))
+ (check-for (lambda (l) (string-prefix? l ":public key packet:")) dump
+ "Public key packet not found")
+ (check-exported-key dump keyid)))
+
+(define (check-exported-private-key packet-dump keyid)
+ (let ((dump (string-split-newlines packet-dump)))
+ (check-for (lambda (l) (string-prefix? l ":secret key packet:")) dump
+ "Secret key packet not found")
+ (check-exported-key dump keyid)))
+
+(lettmp
+ ;; Prepare two temporary files for communication with the fake
+ ;; pinentry program.
+ (logfile ppfile)
+
+ (define (prepare-passphrases . passphrases)
+ (call-with-output-file ppfile
+ (lambda (port)
+ (for-each (lambda (passphrase)
+ (display passphrase port)
+ (display #\newline port)) passphrases))))
+
+ (define CONFIRM "fake-entry being started to CONFIRM the weak phrase")
+
+ (define (assert-passphrases-consumed)
+ (call-with-input-file ppfile
+ (lambda (port)
+ (unless
+ (eof-object? (peek-char port))
+ (fail (string-append
+ "Expected all passphrases to be consumed, but found: "
+ (read-all port)))))))
+
+ (setenv "PINENTRY_USER_DATA"
+ (string-append "--logfile=" logfile " --passphrasefile=" ppfile) #t)
+
+ (for-each-p
+ "Checking key export"
+ (lambda (keyid)
+ (tr:do
+ (tr:pipe-do
+ (pipe:gpg `(--export ,keyid))
+ (pipe:gpg '(--list-packets)))
+ (tr:call-with-content check-exported-public-key keyid))
+
+ (if (string=? "D74C5F22" keyid)
+ ;; Key D74C5F22 is protected by a passphrase. Prepare this
+ ;; one. Currently, GnuPG does not ask for an export passphrase
+ ;; in this case.
+ (prepare-passphrases usrpass1))
+
+ (tr:do
+ (tr:pipe-do
+ (pipe:gpg `(--export-secret-keys ,keyid))
+ (pipe:gpg '(--list-packets)))
+ (tr:call-with-content check-exported-private-key keyid))
+
+ (assert-passphrases-consumed))
+ '("D74C5F22" "C40FDECF" "ECABF51D")))
diff --git a/tests/openpgp/fake-pinentry.c b/tests/openpgp/fake-pinentry.c
new file mode 100644
index 0000000..fb0c6ae
--- /dev/null
+++ b/tests/openpgp/fake-pinentry.c
@@ -0,0 +1,318 @@
+/* Fake pinentry program for the OpenPGP test suite.
+ *
+ * Copyright (C) 2016 g10 code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+static FILE *log_stream;
+
+
+static int
+reply (const char *fmt, ...)
+{
+ int result;
+ va_list ap;
+
+ if (log_stream)
+ {
+ fprintf (log_stream, "> ");
+ va_start (ap, fmt);
+ vfprintf (log_stream, fmt, ap);
+ va_end (ap);
+ }
+ va_start (ap, fmt);
+ result = vprintf (fmt, ap);
+ va_end (ap);
+
+ fflush (stdout);
+ return result;
+}
+
+
+/* Return the first line from FNAME, removing it from the file. */
+static char *
+get_passphrase (const char *fname)
+{
+ char *passphrase = NULL;
+ size_t fname_len;
+ char *fname_new;
+ FILE *source, *sink;
+ char linebuf[80];
+
+ fname_len = strlen (fname);
+ fname_new = malloc (fname_len + 5);
+ if (fname_new == NULL)
+ {
+ perror ("malloc");
+ exit (1);
+ }
+ snprintf (fname_new, fname_len + 5, "%s.new", fname);
+
+ source = fopen (fname, "r");
+ if (! source)
+ {
+ perror (fname);
+ exit (1);
+ }
+
+ sink = fopen (fname_new, "w");
+ if (! sink)
+ {
+ perror (fname_new);
+ exit (1);
+ }
+
+ while (fgets (linebuf, sizeof linebuf, source))
+ {
+ linebuf[sizeof linebuf - 1] = 0;
+ if (passphrase == NULL)
+ {
+ passphrase = strdup (linebuf);
+ if (passphrase == NULL)
+ {
+ perror ("strdup");
+ exit (1);
+ }
+ }
+ else
+ fputs (linebuf, sink);
+ }
+
+ if (ferror (source))
+ {
+ perror (fname);
+ exit (1);
+ }
+
+ if (ferror (sink))
+ {
+ perror (fname_new);
+ exit (1);
+ }
+
+ fclose (source);
+ fclose (sink);
+ if (remove (fname))
+ {
+ fprintf (stderr, "Failed to remove %s: %s",
+ fname, strerror (errno));
+ exit (1);
+ }
+
+ if (rename (fname_new, fname))
+ {
+ fprintf (stderr, "Failed to rename %s to %s: %s",
+ fname, fname_new, strerror (errno));
+ exit (1);
+ }
+
+ free (fname_new);
+ return passphrase;
+}
+
+
+#define whitespacep(p) (*(p) == ' ' || *(p) == '\t' \
+ || *(p) == '\r' || *(p) == '\n')
+
+/* rstrip line. */
+static void
+rstrip (char *buffer)
+{
+ char *p;
+ if (!*buffer)
+ return; /* This is to avoid p = buffer - 1 */
+ for (p = buffer + strlen (buffer) - 1; p >= buffer; p--)
+ {
+ if (! whitespacep (p))
+ break;
+ *p = 0;
+ }
+}
+
+
+/* Skip over options in LINE.
+
+ Blanks after the options are also removed. Options are indicated
+ by two leading dashes followed by a string consisting of non-space
+ characters. The special option "--" indicates an explicit end of
+ options; all what follows will not be considered an option. The
+ first no-option string also indicates the end of option parsing. */
+char *
+skip_options (const char *line)
+{
+ while (whitespacep (line))
+ line++;
+ while (*line == '-' && line[1] == '-')
+ {
+ while (*line && !whitespacep (line))
+ line++;
+ while (whitespacep (line))
+ line++;
+ }
+ return (char*) line;
+}
+
+
+/* Return a pointer to the argument of the option with NAME. If such
+ an option is not given, NULL is returned. */
+char *
+option_value (const char *line, const char *name)
+{
+ char *s;
+ int n = strlen (name);
+
+ s = strstr (line, name);
+ if (s && s >= skip_options (line))
+ return NULL;
+ if (s && (s == line || whitespacep (s-1))
+ && s[n] && (whitespacep (s+n) || s[n] == '='))
+ {
+ s += n + 1;
+ s += strspn (s, " ");
+ if (*s && !whitespacep(s))
+ return s;
+ }
+ return NULL;
+}
+
+int
+main (int argc, char **argv)
+{
+ char *args;
+ char *option_user_data = NULL;
+ int got_environment_user_data;
+ char *logfile;
+ char *passphrasefile;
+ char *passphrase;
+
+ /* We get our options via PINENTRY_USER_DATA. */
+ (void) argc, (void) argv;
+
+ setvbuf (stdin, NULL, _IOLBF, BUFSIZ);
+ setvbuf (stdout, NULL, _IOLBF, BUFSIZ);
+
+ args = getenv ("PINENTRY_USER_DATA");
+ got_environment_user_data = !!args;
+ if (! args)
+ args = "";
+
+ restart:
+ logfile = option_value (args, "--logfile");
+ if (logfile)
+ {
+ char *p = logfile, more;
+ while (*p && ! whitespacep (p))
+ p++;
+ more = !! *p;
+ *p = 0;
+ args = more ? p+1 : p;
+
+ log_stream = fopen (logfile, "a");
+ if (! log_stream)
+ {
+ perror (logfile);
+ return 1;
+ }
+ }
+
+ passphrasefile = option_value (args, "--passphrasefile");
+ if (passphrasefile)
+ {
+ char *p = passphrasefile, more;
+ while (*p && ! whitespacep (p))
+ p++;
+ more = !! *p;
+ *p = 0;
+ args = more ? p+1 : p;
+
+ passphrase = get_passphrase (passphrasefile);
+ if (! passphrase)
+ {
+ reply ("# Passphrasefile '%s' is empty. Terminating.\n",
+ passphrasefile);
+ return 1;
+ }
+
+ rstrip (passphrase);
+ }
+ else
+ {
+ passphrase = skip_options (args);
+ if (*passphrase == 0)
+ passphrase = "no PINENTRY_USER_DATA -- using default passphrase";
+ }
+
+ reply ("# fake-pinentry(%u) started. Passphrase='%s'.\n",
+ (unsigned int)getpid (), passphrase);
+ reply ("OK - what's up?\n");
+
+ while (! feof (stdin))
+ {
+ char buffer[1024];
+
+ if (fgets (buffer, sizeof buffer, stdin) == NULL)
+ break;
+
+ if (log_stream)
+ fprintf (log_stream, "< %s", buffer);
+
+ rstrip (buffer);
+
+#define OPT_USER_DATA "OPTION pinentry-user-data="
+
+ if (strncmp (buffer, "GETPIN", 6) == 0)
+ reply ("D %s\n", passphrase);
+ else if (strncmp (buffer, "BYE", 3) == 0)
+ {
+ reply ("OK\n");
+ break;
+ }
+ else if (strncmp (buffer, OPT_USER_DATA, strlen (OPT_USER_DATA)) == 0)
+ {
+ if (got_environment_user_data)
+ {
+ reply ("OK - I already got the data from the environment.\n");
+ continue;
+ }
+
+ if (log_stream)
+ fclose (log_stream);
+ log_stream = NULL;
+ free (option_user_data);
+ option_user_data = args = strdup (buffer + strlen (OPT_USER_DATA));
+ goto restart;
+ }
+
+ reply ("OK\n");
+ }
+
+#undef OPT_USER_DATA
+
+ reply ("# Connection terminated.\n");
+ if (log_stream)
+ fclose (log_stream);
+
+ free (option_user_data);
+ return 0;
+}
diff --git a/tests/openpgp/genkey1024.scm b/tests/openpgp/genkey1024.scm
new file mode 100755
index 0000000..4edf490
--- /dev/null
+++ b/tests/openpgp/genkey1024.scm
@@ -0,0 +1,53 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-environment)
+
+(define (genkey config)
+ (pipe:do
+ (pipe:echo config)
+ (pipe:spawn `(,(tool 'gpg) --quiet --batch --generate-key))))
+
+(info "Checking batch key generation")
+(genkey "Key-Type: DSA
+Key-Length: 1024
+Subkey-Type: ELG
+Subkey-Length: 1024
+Name-Real: Harry H.
+Name-Comment: test key
+Name-Email: hh@@ddorf.de
+Expire-Date: 1
+%no-protection
+%transient-key
+%commit
+")
+
+(if (have-pubkey-algo? "RSA")
+ (genkey "Key-Type: RSA
+Key-Length: 1024
+Key-Usage: sign,encrypt
+Name-Real: Harry A.
+Name-Comment: RSA test key
+Name-Email: hh@@ddorf.de
+Expire-Date: 2
+%no-protection
+%transient-key
+%commit
+"))
diff --git a/tests/openpgp/gpgconf.scm b/tests/openpgp/gpgconf.scm
new file mode 100644
index 0000000..16e435d
--- /dev/null
+++ b/tests/openpgp/gpgconf.scm
@@ -0,0 +1,47 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2017 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-environment)
+
+(for-each-p'
+ "Checking reading and writing configuration via gpgconf... "
+ (lambda (name opt make-value)
+ (call-with-progress
+ ""
+ (lambda (progress)
+ (do ((i 0 (+ 1 i))) ((> i 12) #t)
+ (let ((value (make-value i)))
+ (if value
+ (begin
+ (opt::update value)
+ (assert (equal? value (opt::value))))
+ (begin
+ (opt::clear)
+ (assert (or (not (opt::value)) (string=? "" (opt::value)))))))
+ (progress ".")))))
+ (lambda (name . rest) name)
+ (list "keyserver" "verbose")
+ (list (gpg-config 'gpg "keyserver")
+ (gpg-config 'gpg "verbose"))
+ (list (lambda (i) (if (even? i) "hkp://foo.bar" "hkps://bar.baz"))
+ ;; gpgconf: argument for option verbose of type 0 (none) must
+ ;; be positive
+ (lambda (i) (+ 1 i))
+ (lambda (i) (if (even? i) #f 1))))
diff --git a/tests/openpgp/gpgtar.scm b/tests/openpgp/gpgtar.scm
new file mode 100755
index 0000000..906707f
--- /dev/null
+++ b/tests/openpgp/gpgtar.scm
@@ -0,0 +1,94 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(catch (skip "gpgtar not built")
+ (call-check `(,(tool 'gpgtar) --help)))
+
+(define testfiles (append plain-files data-files))
+(define gpgargs
+ (if have-opt-always-trust
+ "--no-permission-warning --always-trust"
+ "--no-permission-warning"))
+
+(define (do-test create-flags inspect-flags extract-flags)
+ (lettmp (archive)
+ (call-check `(,(tool 'gpgtar) --gpg ,(tool 'gpg) --gpg-args ,gpgargs
+ ,@create-flags
+ --output ,archive
+ ,@testfiles))
+ (tr:do
+ (tr:pipe-do
+ (pipe:spawn `(,(tool 'gpgtar) --gpg ,(tool 'gpg) --gpg-args ,gpgargs
+ --list-archive ,@inspect-flags
+ ,archive)))
+ (tr:call-with-content
+ (lambda (c)
+ (unless (all (lambda (f) (string-contains? c f)) testfiles)
+ (fail "some file(s) are missing from archive")))))
+
+ (with-temporary-working-directory
+ (call-check `(,(tool 'gpgtar) --gpg ,(tool 'gpg) --gpg-args ,gpgargs
+ --tar-args --directory=.
+ ,@extract-flags
+ ,archive))
+
+ (for-each
+ (lambda (f) (unless (call-with-input-file f (lambda (x) #t))
+ (fail (string-append "missing file: " f))))
+ testfiles))))
+
+(info "Checking gpgtar without encryption")
+(do-test '(--skip-crypto --encrypt) '(--skip-crypto)
+ '(--skip-crypto --decrypt))
+
+(info "Checking gpgtar without encryption with nicer actions")
+(do-test '(--create) '(--skip-crypto) '(--extract))
+
+(info "Checking gpgtar with asymmetric encryption")
+(do-test `(--encrypt --recipient ,usrname2) '() '(--decrypt))
+
+(info "Checking gpgtar with asymmetric encryption and signature")
+(do-test `(--encrypt --recipient ,usrname2 --sign --local-user ,usrname3)
+ '() '(--decrypt))
+
+(info "Checking gpgtar with signature")
+(do-test `(--sign --local-user ,usrname3) '() '(--decrypt))
+
+(lettmp (passphrasefile)
+ (letfd ((fd (open passphrasefile (logior O_WRONLY O_CREAT O_BINARY) #o600)))
+ (display "streng geheimes hupsipupsi" (fdopen fd "wb")))
+
+ (let ((ppflags `(--gpg-args ,(string-append "--passphrase-file="
+ passphrasefile))))
+ (info "Checking gpgtar with symmetric encryption")
+ (do-test `(,@ppflags --symmetric) ppflags (cons '--decrypt ppflags))
+
+ (info "Checking gpgtar with symmetric encryption and chosen cipher")
+ (do-test `(,@ppflags --symmetric --gpg-args
+ ,(string-append "--cipher="
+ (car (force all-cipher-algos))))
+ ppflags (cons '--decrypt ppflags))
+
+ (info "Checking gpgtar with both symmetric and asymmetric encryption")
+ (do-test `(,@ppflags --symmetric --encrypt --recipient ,usrname2
+ --sign --local-user ,usrname3)
+ ppflags (cons '--decrypt ppflags))))
diff --git a/tests/openpgp/gpgv-forged-keyring.scm b/tests/openpgp/gpgv-forged-keyring.scm
new file mode 100755
index 0000000..886d265
--- /dev/null
+++ b/tests/openpgp/gpgv-forged-keyring.scm
@@ -0,0 +1,68 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(define msg_signed_asc "
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA256
+
+This is an example text file to demonstrate a problem.
+
+Using forged-keyring.gpg with signature cache, it looks like it is
+signed by the following key:
+
+ Echo Test (demo key) <echo@example.net>
+
+But actually not.
+
+It is signed by a key (steve.biko@example.net) distributed as:
+
+ gnupg/tests/openpgp/samplekeys/rsa-rsa-sample-1.asc
+
+in GnuPG.
+
+The forged-keyring.gpg file is created by a key in
+
+ gnupg/tests/openpgp/pubdemo.asc
+
+Replacing the raw key material packet by one of rsa-rsa-sample-1.asc.
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v2
+
+iQEcBAEBCAAGBQJXp+5MAAoJEKpD8dzH/tG3bGMH/1idFLJAaMxkrq+JguvAboiN
+tAA44IdAgJvAxtR5w5fgfed7PfsH70+tj54/ZTObt7rZDIlj/YBQ7XeCwd7/O5vx
+W0QtjjAxMuAPH80rVv4JIoflxV/deD8YaV9EhPE+6W5G0Z8SYL9B2RzdBVMwJY9+
+OZGJeKnUZ92Zg9jFr+H5gQNSeYdDHVDWYxr/xJUf0jYsZvAIBfB1mcSK1niiiVBv
+GAcUC/I8g18a7pCS9Qf9iZflqxX4AXfocAGQqQAiG4744OCNhVa5q6TScqhaGUah
+N1Glbw1OJfP1q+QFPMPKoCsTYmZpuugq2b5gV/eH0Abvk2pG4Fo/YTDPHhec7Jk=
+=NnY/
+-----END PGP SIGNATURE-----
+")
+
+(for-each-p
+ "Checking that a signature by bad key should not be verified"
+ (lambda (armored-file)
+ (catch '()
+ (pipe:do
+ (pipe:echo (eval armored-file (current-environment)))
+ (pipe:spawn `(,@GPGV --keyring ,(in-srcdir "tests" "openpgp" "forged-keyring.gpg"))))
+ (fail "verification succeeded but should not")))
+ '(msg_signed_asc))
diff --git a/tests/openpgp/gpgv.scm b/tests/openpgp/gpgv.scm
new file mode 100755
index 0000000..819d15f
--- /dev/null
+++ b/tests/openpgp/gpgv.scm
@@ -0,0 +1,75 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016-2017 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(load (in-srcdir "tests" "openpgp" "signed-messages.scm"))
+(setup-legacy-environment)
+
+(define keyring (if (file-exists? "pubring.kbx") "pubring.kbx" "pubring.gpg"))
+
+;;
+;; Two simple tests to check that verify fails for bad input data
+;;
+(for-each-p
+ "Checking bogus signature"
+ (lambda (char)
+ (lettmp (x)
+ (call-with-binary-output-file
+ x
+ (lambda (port)
+ (display (make-string 64 (integer->char (string->number char)))
+ port)))
+ (if (= 0 (call `(,@gpgv --keyring ,keyring ,x data-500)))
+ (fail "no error code from verify"))))
+ '("#x2d" "#xca"))
+
+;; Fixme: We need more tests with manipulated cleartext signatures.
+
+;;
+;; Now run the tests.
+;;
+(for-each-p
+ "Checking that a valid signature is verified as such"
+ (lambda (armored-file)
+ (pipe:do
+ (pipe:echo (eval armored-file (current-environment)))
+ (pipe:spawn `(,@gpgv --keyring ,keyring))))
+ '(msg_ols_asc msg_cols_asc msg_sl_asc msg_oolss_asc msg_cls_asc msg_clss_asc))
+
+(for-each-p
+ "Checking that an invalid signature is verified as such"
+ (lambda (armored-file)
+ (catch '()
+ (pipe:do
+ (pipe:echo (eval armored-file (current-environment)))
+ (pipe:spawn `(,@gpgv --keyring ,keyring)))
+ (fail "verification succeeded but should not")))
+ '(bad_ls_asc bad_fols_asc bad_olsf_asc bad_ools_asc))
+
+
+;; Need to import the ed25519 sample key used for the next two tests.
+(call-check `(,@gpg --quiet --yes
+ --import ,(in-srcdir "tests" "openpgp" key-file2)))
+(for-each-p
+ "Checking that a valid Ed25519 signature is verified as such"
+ (lambda (armored-file)
+ (pipe:do
+ (pipe:echo (eval armored-file (current-environment)))
+ (pipe:spawn `(,@gpgv --keyring ,keyring))))
+ '(msg_ed25519_rshort msg_ed25519_sshort))
diff --git a/tests/openpgp/import-revocation-certificate.scm b/tests/openpgp/import-revocation-certificate.scm
new file mode 100644
index 0000000..c685dc5
--- /dev/null
+++ b/tests/openpgp/import-revocation-certificate.scm
@@ -0,0 +1,37 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+;; XXX because of --always-trust, the trustdb is not created.
+;; Therefore, we redefine GPG without --always-trust.
+(define gpg `(,(tool 'gpg) --no-permission-warning))
+
+(info "Checking key revocation.")
+(call-check `(,@gpg --import ,(in-srcdir "tests" "openpgp" "samplemsgs"
+ "revoke-2D727CC768697734.asc")))
+(let loop ((output (gpg-with-colons '(--list-secret-keys "2D727CC768697734"))))
+ (unless (null? output)
+ (let ((line (car output))
+ (rest (cdr output)))
+ (when (member (car line) '("sec" "uid" "ssb"))
+ (unless (equal? (cadr line) "r")
+ (fail (car line) "not revoked.")))
+ (loop rest))))
diff --git a/tests/openpgp/import.scm b/tests/openpgp/import.scm
new file mode 100755
index 0000000..1f4cb2e
--- /dev/null
+++ b/tests/openpgp/import.scm
@@ -0,0 +1,61 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-environment)
+
+(info "Checking bug 894: segv importing certain keys.")
+(call-check `(,(tool 'gpg) --import ,(in-srcdir "tests" "openpgp" "bug894-test.asc")))
+
+(define keyid "0xC108E83A")
+(info "Checking bug 1223: designated revoker sigs are not properly merged.")
+(call `(,(tool 'gpg) --delete-key --batch --yes ,keyid))
+(call `(,(tool 'gpg) --import ,(in-srcdir "tests" "openpgp" "bug1223-bogus.asc")))
+(call `(,(tool 'gpg) --import ,(in-srcdir "tests" "openpgp" "bug1223-good.asc")))
+(tr:do
+ (tr:pipe-do
+ (pipe:gpg `(--list-keys --with-colons ,keyid)))
+ (tr:call-with-content
+ (lambda (c)
+ ;; XXX we do not have a regexp library
+ (unless (any (lambda (line)
+ (and (string-prefix? line "rvk:")
+ (string-contains? line ":0EE5BE979282D80B9F7540F1CCD2ED94D21739E9:")))
+ (string-split-newlines c))
+ (exit 1)))))
+
+(define fpr1 "9E669861368BCA0BE42DAF7DDDA252EBB8EBE1AF")
+(define fpr2 "A55120427374F3F7AA5F1166DDA252EBB8EBE1AF")
+(info "Checking import of two keys with colliding long key ids.")
+(call `(,(tool 'gpg) --delete-key --batch --yes ,fpr1 ,fpr2))
+(call `(,(tool 'gpg) --import ,(in-srcdir "tests" "openpgp" "samplekeys/dda252ebb8ebe1af-1.asc")))
+(call `(,(tool 'gpg) --import ,(in-srcdir "tests" "openpgp" "samplekeys/dda252ebb8ebe1af-2.asc")))
+(tr:do
+ (tr:pipe-do
+ (pipe:gpg `(--list-keys --with-colons ,fpr1 ,fpr2)))
+ (tr:call-with-content
+ (lambda (c)
+ ;; XXX we do not have a regexp library
+ (let ((keys (filter
+ (lambda (line)
+ (and (string-prefix? line "pub:")
+ (string-contains? line ":4096:1:DDA252EBB8EBE1AF:")))
+ (string-split-newlines c))))
+ (unless (= 2 (length keys))
+ (fail "Importing keys with long id collision failed"))))))
diff --git a/tests/openpgp/issue2015.scm b/tests/openpgp/issue2015.scm
new file mode 100755
index 0000000..2f0672d
--- /dev/null
+++ b/tests/openpgp/issue2015.scm
@@ -0,0 +1,31 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-environment)
+
+(info "Checking passphrase cache (issue2015)...")
+(call-check `(,(tool 'gpg-preset-passphrase)
+ --preset --passphrase some_passphrase some_id))
+
+(let ((response (call-popen `(,(tool 'gpg-connect-agent))
+ "GET_PASSPHRASE --no-ask some_id X X X")))
+ (unless (string=? (string-rtrim char-whitespace? response)
+ "OK 736F6D655F70617373706872617365")
+ (fail "Could not retrieve passphrase from cache:" response)))
diff --git a/tests/openpgp/issue2346.scm b/tests/openpgp/issue2346.scm
new file mode 100755
index 0000000..9c29516
--- /dev/null
+++ b/tests/openpgp/issue2346.scm
@@ -0,0 +1,28 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-environment)
+
+(define key (in-srcdir "tests" "openpgp" "samplekeys/issue2346.gpg"))
+
+(info "Checking import statistics (issue2346)...")
+(let ((status (call-popen `(,@GPG --status-fd=1 --import ,key) "")))
+ (unless (string-contains? status "IMPORT_RES 1 0 1 0 0 0 0 0 0 1 1 0 0 0 0")
+ (fail "Unexpected number of keys imported" status)))
diff --git a/tests/openpgp/issue2417.scm b/tests/openpgp/issue2417.scm
new file mode 100755
index 0000000..32fe47f
--- /dev/null
+++ b/tests/openpgp/issue2417.scm
@@ -0,0 +1,32 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-environment)
+
+(define keyfile (in-srcdir "tests" "openpgp" "samplekeys" "rsa-rsa-sample-1.asc"))
+
+(define (touch file-name)
+ (close (open file-name (logior O_WRONLY O_BINARY O_CREAT) #o600)))
+
+(info "Checking robustness wrt empty databases in gnupghome (issue2417)...")
+(touch "trustdb.gpg")
+(touch "pubring.gpg")
+(touch "pubring.kbx")
+(call-check `(,(tool 'GPG) --import ,keyfile))
diff --git a/tests/openpgp/issue2419.scm b/tests/openpgp/issue2419.scm
new file mode 100755
index 0000000..641fb32
--- /dev/null
+++ b/tests/openpgp/issue2419.scm
@@ -0,0 +1,29 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-environment)
+
+(info "Checking iobuf_peek corner case (issue2419)...")
+(lettmp
+ (onebyte)
+ (dearmor (in-srcdir "tests" "openpgp" "samplemsgs/issue2419.asc") onebyte)
+ (catch (assert (string-contains? (car *error*) "invalid packet"))
+ (call-popen `(,@GPG --list-packets ,onebyte) "")
+ (fail "Expected an error but got none")))
diff --git a/tests/openpgp/issue2929.scm b/tests/openpgp/issue2929.scm
new file mode 100644
index 0000000..d5c94cf
--- /dev/null
+++ b/tests/openpgp/issue2929.scm
@@ -0,0 +1,32 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2017 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-environment)
+
+(catch (skip "Tofu not supported")
+ (call-check `(,@gpg --trust-model=tofu --list-config)))
+
+;; Redefine GPG without --always-trust and TOFU trust model.
+(define gpg `(,(tool 'gpg) --no-permission-warning --trust-model=tofu))
+
+(info "Checking TOFU trust model with ultimately trusted keys (issue2929).")
+(call-check `(,@gpg --quick-generate-key frob@example.org))
+(call-check `(,@gpg --sign gpg.conf))
+(call-check `(,@gpg --verify gpg.conf.gpg))
diff --git a/tests/openpgp/issue2941.scm b/tests/openpgp/issue2941.scm
new file mode 100755
index 0000000..8f625eb
--- /dev/null
+++ b/tests/openpgp/issue2941.scm
@@ -0,0 +1,34 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2017 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(define (check-failure options)
+ (let ((command `(,@gpg ,@options)))
+ (catch '()
+ (call-check command)
+ (error "Expected an error, but got none when executing" command))))
+
+(for-each-p
+ "Checking invocation with invalid file descriptors (issue2941)."
+ (lambda (option)
+ (check-failure `(,(string-append "--" option "=23") --sign gpg.conf)))
+ '("status-fd" "attribute-fd" "logger-fd"
+ "override-session-key-fd" "passphrase-fd" "command-fd"))
diff --git a/tests/openpgp/key-selection.scm b/tests/openpgp/key-selection.scm
new file mode 100644
index 0000000..511c2e2
--- /dev/null
+++ b/tests/openpgp/key-selection.scm
@@ -0,0 +1,83 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+;; This test assumes a fixed time of 2004-01-01.
+
+ ;; Redefine gpg with a fixed time.
+(define gpg `(,@gpg --faked-system-time=1072911600))
+
+;; We have a number of keys for Mr. Acejlnu Acdipr <acdipr@example.org>.
+(define mailbox "acdipr@example.org")
+
+;; The keys are sorted, from the least relevant to the most relevant
+;; key.
+(define keys
+ '(("ED087E9D3394340738E20A244892A3CF8F65EBAC"
+ "no encryption-capable subkey, created: 2003-11-30, expires: 2006-11-29"
+ 4)
+ ("D7388651A1B7466D03B538428178E04B0BAA385B"
+ "encryption-capable subkey, created: 2000-12-31, expired: 2001-12-31"
+ 0)
+ ("DDEF1BEC66C8BAC8D69CED2AEABED840EC98B024"
+ "encryption-capable subkey, created: 2001-12-31, expires: 2006-12-30"
+ 1)
+ ("03FCFEDE014027DD897AD2F23D32670A96A9C2BF"
+ "encryption-capable subkey, created: 2002-12-31, expires: 2005-12-30"
+ 2)
+ ("B95BD6175CB6339244355BA160B8117E6119CED6"
+ "encryption-capable subkeys, last created: 2003-05-31, expires: 2005-05-30"
+ 3)))
+
+;; Accessors for the elements of KEYS.
+(define :fpr car)
+(define :comment cadr)
+(define :number caddr)
+(define (:filename key)
+ (in-srcdir "tests" "openpgp" "key-selection"
+ (string-append (number->string (:number key)) ".asc")))
+
+(define (delete-keys which)
+ (call-check `(,@gpg --delete-keys ,@(map :fpr which))))
+
+(define (import-keys which)
+ (call-check `(,@gpg --import ,@(map :filename which))))
+
+(for-each-p'
+ "Checking key selection"
+ (lambda (set)
+ (import-keys set)
+ (let ((fpr (list-ref (assoc "fpr"
+ (gpg-with-colons `(--locate-key ,mailbox)))
+ 9))
+ (expected (:fpr (last set))))
+ (unless (equal? fpr expected)
+ (display "Given keys ")
+ (apply echo (map :fpr set))
+ (echo "This is what --locate-key says:")
+ (display (call-popen `(,@gpg --locate-key ,mailbox) ""))
+ (echo "This is the key we expected:")
+ (display (call-popen `(,@gpg --list-keys ,expected) ""))
+ (fail "Expected" expected "but got" fpr)))
+ (delete-keys set))
+ (lambda (set)
+ (length set))
+ (filter (lambda (x) (not (null? x))) (powerset keys)))
diff --git a/tests/openpgp/key-selection/0.asc b/tests/openpgp/key-selection/0.asc
new file mode 100644
index 0000000..d40a98b
--- /dev/null
+++ b/tests/openpgp/key-selection/0.asc
@@ -0,0 +1,30 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQENBDpPvC8BCACqDbU+2znCURAocNMmcwCSYVl5l4Zbx6jcy9ON7y12Ai7CRSbX
+8Nb8kggit02pNFtb1l2NKad7DqR1f/WPqkQjZ6rvFHKEOsupqrUhpQ6dU3H94wuO
+g4M2PGsaxKAcw24qIoKkTotecLgUFMhduIq7u8kTnalTOW1o/18moVuoVNkDdO4Y
+I7n/dloVNv5Xkm5bS4VBdvUzJ9gvbqkynud/L6pSFeng0vVJQMN3tVbApcNzhLBs
+G5Fvf9Rve4V8xTeBYQ+VRO7H9nvaS8YFf07kTwUDS69Vs8qIaLKOQJL3F75CileN
+K7fb9OC3J4PNF0CDz+e2KkRRF6Q/xS8KXF9rABEBAAG0I0FjZWpsbnUgQWNkaXBy
+IDxhY2RpcHJAZXhhbXBsZS5vcmc+iQFUBBMBCAA+FiEE1ziGUaG3Rm0DtThCgXjg
+SwuqOFsFAjpPvC8CGwMFCQHhM4AFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AACgkQ
+gXjgSwuqOFt7Lgf8DFDVQ4JykT8njX0+JkemSL2UUDH2iVRWkU6tKZPGneEnQGMm
+iRfSX0im0pFHWxJ0vZsmUNq33Vr2sbvppT8Ti1rBx4TrdZ7PSEIEi1KTVSx6GKjr
+2ObCax2u1p+u+tC35GfhV1Y1pUcSZXc45C1o259ivekRJY/fw9DrvR7154S3ygjp
+lkEM4PC33216XMTqUG1sAWw40aDtKaiyp5J8zqLKXXjCnZsTWdj4uxB7E5WPjaEF
+ylON/h+Hfw2RMzlYRGTbUu2G/Ma0TiycGJvT78myCpnc5akcKVZu1Wu4VDBqBC1N
+dVcTzhJ5T4gwFCWHif3/MYqTVBnZSAVURtI3V7kBDQQ6T7wvAQgAuF5JaVAE9/Vv
+K1U+VSAAhWMGSp6fwezgWdj0rn1GBx3DtqQkYXoLRjTrlBf1qOO6NPbBUi1gz8R+
+IQTHsesIXiUSlMige3/HxdSOsbzKipm1SGJedqUz3H03+yfr82NT+QvQmlEGX9k6
+goPY9t3r+O3F6ab4mc5NxFKhj2XvbRyf8I9J+3w6zXBWwsgLHacTCa13zGz6B0NH
+dCk/2B6HTJeIJWpHdALQXp0/JcKWksw0Hsihpdu0QploUSPihZostRUKszOkugeu
+W0t3fmt6on4fIFWveh9NSVDYIHKVMRU8cl5vRXNNRTsYQOarIvjmoUHv5u+UpZcc
+iE/7wILNhQARAQABiQE8BBgBCAAmFiEE1ziGUaG3Rm0DtThCgXjgSwuqOFsFAjpP
+vC8CGwwFCQHhM4AACgkQgXjgSwuqOFv9GAgAkACyK3Km4jFBqw7ah2xMxWCkdpgu
+DdTi64ra6GyMQk/Lem8DzBO/ER/cavV9lg61qCOy7ecCNs7MhPiWZIod2bcV3JDZ
+AglnGgTQ+lSpPXFCk3eoRktRsXesgQ1dE30uR9pypEqZ0BYNZZ2G2hRqAnRgUOOI
+7THmf/X5w5KPKLlm3zOlGQomFy6lfOR9Zd5/QoKRNmuD9gNfSE+3vBvr+ISQPIev
+Ch2qeC/N0BP5EoVE4SXp8l2oaaVJLi/Yx2J6vfximeeaBPxsKjuA+GJu6IIhegnY
+X4kCxWStla+KuN0p0iNUh002pKybISuqyI9vgImH9Nh22Nf7mcRQWflR6A==
+=nyjX
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/key-selection/1.asc b/tests/openpgp/key-selection/1.asc
new file mode 100644
index 0000000..fea379c
--- /dev/null
+++ b/tests/openpgp/key-selection/1.asc
@@ -0,0 +1,30 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQENBDww7w4BCADCvhkDDCAAtDpLCUa2ryPqWxlSSVKdyY9ecqjgEswijsZ+2T6O
+Xr/50POpLbW9IWvHdvcifXUk1YZg8wLcnVIMwiZsdNSDM3MycoPoNc7pL5MaPGL6
+e9u+8HWX6aowOo5st6Y57HUeaKReH1Peb0avoEUIE9l4xqVx41AYrKViS7Zp5p9A
+67thNKMisZ8aYutlhmVQB/uDO7XiKal07vjftf6aZazNBC5ZBOj4G+/TLcKMox8h
+AaUJTkqsJcSCZTc7cMVjikmWItgKm6wIceGTpUGSvvZ3TnWUtgq3ivaMQrpyN3RT
+tVM5uO2Mh8Uzkq9YWh2V7IT+jGKztrpdPKu3ABEBAAG0I0FjZWpsbnUgQWNkaXBy
+IDxhY2RpcHJAZXhhbXBsZS5vcmc+iQFUBBMBCAA+FiEE3e8b7GbIusjWnO0q6r7Y
+QOyYsCQFAjww7w4CGwMFCQlmAYAFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AACgkQ
+6r7YQOyYsCT0awf+NENO1grzmRfsyl8ODREmUlnnUAaRiZGQ0h+JkooXiwcm/p5O
+DupjRc5OLluDtnjTLMBwNk5ysX6yqSNTni9qCCpm62PaIopG+r8RyFPp4aRjR1Q3
+mbwHkKifLRBxDxeCDKdrqFs7hkVCYOxjyiaEZ2BYogqFDwHFoiE6UwQvwZfpNWex
+4Zx8nhoGpcegMMEiGREWCTi0H+zJrYOiVzV2jPQF5lkFkwYMQKNaNQv3L5v2/5AC
+Nu6Kej+oYcw/EA+o3OXYLxwa+tijfKqUxtndFsQS/lYSUNszxrcm7dOAx52DCMpC
+8MNHmwe3qmofO6G9svqG02bIZTdyJBob5nNBD7kBDQQ8MO8OAQgAttn9ru3Ou6+A
+lAqbV7fAbpdeIF5bHy/QZtLxa2dpG8BTOXDcoMp9MUyKjafHbNr+z5unqqTfduXy
+oRdJ1D/iXbSpcRkMKRJz4fa+uPNN5SiGzrjxHTcALPG8ctTUvdNrV+Z5VkssU+FW
+LQD+s5SQWn848kYTacrDL22JshIpekmz3ztDoNGOZxVj2DwF/QXDeaRhXT9ngB3c
+PY8x7e8yIvmAcg8olt9rKTpkGXZHWAyBpyGzBJkxM+wfiNreGMNUkv41G/R4d1Lv
+xMlGF05xrBJX9YrV1pRM+EdS4WOs2gvFT3qnBzFAQBZ9nqaLAFVxw0Sl7C+wSQPk
+7ZPIKYANFwARAQABiQE8BBgBCAAmFiEE3e8b7GbIusjWnO0q6r7YQOyYsCQFAjww
+7w4CGwwFCQlmAYAACgkQ6r7YQOyYsCSDdwf/an06WTTAIwHj8PfXIkywnq3SWfSZ
+yuRaFaDan9en8xAfyw2smNnrHnTk86CZWL6yPTij6JZYynv4OxtSafIoT9LxT7uX
+VpEtSBpTnnojlHFivfRYMGJ9k/EXGgb941W2DTbvQqzafc2u4K3u8KnFOgzfEj5B
+qjYzbt/L2uR2PLOAfYIUYzqTKjdzvSIX2DRvkepHhTwRbCjJrkF/zx0IXFoJeU/k
+6tYK6cNNCFTWT0uLJCflAZMtGpf4KDvjlccNts3mZQbEov+Dymj/nZ9JRgjc2heH
+Pxi5muPMQ8jAc2i4V8vTybozlZ5O/+JkOOOH0ciLpD3buhgYBY309DIVmA==
+=zVE+
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/key-selection/2.asc b/tests/openpgp/key-selection/2.asc
new file mode 100644
index 0000000..4b697f7
--- /dev/null
+++ b/tests/openpgp/key-selection/2.asc
@@ -0,0 +1,30 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQENBD4SIdsBCACqRRWUd9mwgRzVzaDbVLRdNOdyswPYuBKWlHI6Yx0lpfiQK6/X
+rnRoR18lYJ0wBqImd/BJbjNE4bYaMUd+p7HzYIKzv8/DuvZQgovt9VIBn+a3YyCa
+hdAaWEz994fjl8U5IGbrrGuV4XXlFATA6S7KX7CgxgiK/jVnRl1NVcTjOSnasU2J
+LIbh0lawUe0b3HlwT8uFGg/MK3vHGGIalOJRlgeTBAF7zcaTfqoDiAXbbsfaxT4a
+zB1OTRut1VOGBLWCsr09VCAMyz8awQqF81uG6cuv9swo76SuTiMcMMBfdNw3etVa
+kLgL4JnsnMGM7c1fx/mfMUIUHYndDVT5LzQjABEBAAG0I0FjZWpsbnUgQWNkaXBy
+IDxhY2RpcHJAZXhhbXBsZS5vcmc+iQFUBBMBCAA+FiEEA/z+3gFAJ92JetLyPTJn
+Cpapwr8FAj4SIdsCGwMFCQWjmoAFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AACgkQ
+PTJnCpapwr/bGAgAjGWQ3F9RUpeI3ogLLhGMsXmsOxZX1ptNtjL9HiDsrUY5XCS1
+7vZUpRz0/2nscbu7or6Xy8yZtG0vLXwfzeOvHQz/F8tnzruIWBFSAU8WBidxKxmC
+AUlQWg6bAp0aTxyyVi/r719J6k/G/ZOhjgXM243Ck9HNnY2a0h0ArKzPo56N8Cks
+caXshdWxIh3M9uJKSxBCxfDTtqPcU7LjNApaUOFphpAPT9ypE/Zw9BZNTVN6vILr
+I7upnG5PNXybMCDh2XhpXS2E5/rY9Y3/aFKthBws16JMAzBRKMQqWTTC9a8X+4pa
+KcNtQih3X9eRzj4JBAh6cl5qXIbz+32EzXA8drkBDQQ+EiHbAQgAz017pYsm9Sf0
+z5HqOQLx1dwCclzVE5RhvI+qplPT5e9sLG+trbOVpGM6fjWAK/yuxaUJibm/44UX
+cxsTuR7gpAwc+gvwrF3cG6kmT+g4kZ7/I4EyBMZjM9lhlIk77MCTLXcT9ONr7Pm4
+flQO+vM6ZYRFm7DtSHzP2z2Uu9USqgLJumn+V61xQXYj3E2ORczOV3blPVUoI7gl
+aRnVdveEqrucw+miRWq3clykTdbuP39H2nRgY0KXGbOefWh5dRe2okxL5nlhINGL
+lOyj9n4jM6fNp9K8jWeg8YJ7tKRsffrrNnIovslNlkXucYAzM2OveP+JxDdtosSK
+fzWtUSzrmQARAQABiQE8BBgBCAAmFiEEA/z+3gFAJ92JetLyPTJnCpapwr8FAj4S
+IdsCGwwFCQWjmoAACgkQPTJnCpapwr+p6wf/cO8apRVlpRrI2q92j5DJ0IQsBdUv
+Srvp3w8UHZad0VkhgT+edbYHN8VS245ckyWoUBB78XEvxayMF1/Mx0N+u1MOM1dY
+MrAiwbaQnE99yjifwVzZz6wJuJ94MMzWw38j22ZTbIBHPh/4nzSl84sN+KuEcP4f
+C2h7mat4NDO/VRTf7xWuLInS5yGdDOACwROd85ua4YNxo54s5mcd6BVr4upHd1Hj
+0TULgmWvqz49N40VY4GF+38OAC7+DSsdamHVNdTb0fT+KaxTQ0K5BCl+7Oe66CqH
+RWxaXRUD4YMRh1jdgc+j4D3Sj4xhevu0Kd6+7BWxmxWZKdOCiu9TEDBjrg==
+=YqE5
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/key-selection/3.asc b/tests/openpgp/key-selection/3.asc
new file mode 100644
index 0000000..ab2ff73
--- /dev/null
+++ b/tests/openpgp/key-selection/3.asc
@@ -0,0 +1,43 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+vlWlPNIJSTq1Bg==
+=rf5l
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/key-selection/4.asc b/tests/openpgp/key-selection/4.asc
new file mode 100644
index 0000000..6a0ab9b
--- /dev/null
+++ b/tests/openpgp/key-selection/4.asc
@@ -0,0 +1,18 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQENBD/KdpABCAD2wlP1kYHldknjyGTnMOUq9r+3/fJR8n4qVt5TRRlDdyfK3ZxM
+KWStsmkZuK9dMxo4VSOjVeiXdZlHeQU7RlzVPsCNiJ1Qc2HDgHFdmT7eUgOILA12
+36bueRUwVPGmrBEecs0TpNRQ5CVFbO7mC6cTLhT9nRMd+W+BSuuZ8Zm98ebaVh3I
+ml3nPEVhs1UFmIop48RGCt45MZ2mYp77kuAmk8NBJjHy9J4H5UK19r0hla2WY4a3
+Z59hh7kFnNFCM/MhPxd6GwkeXzUF7WSnhzRVIkdv81u2AnIHbo1zD0BUp8Rf64Ns
+3iFAeB1VuR6ZJpEypHiHUJtYPmr9okEmg8EDABEBAAG0I0FjZWpsbnUgQWNkaXBy
+IDxhY2RpcHJAZXhhbXBsZS5vcmc+iQFUBBMBCAA+FiEE7Qh+nTOUNAc44gokSJKj
+z49l66wFAj/KdpACGwMFCQWjmoAFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AACgkQ
+SJKjz49l66xZ7QgA7dBJsQP09LhkYDIu8cJzRU6tqa2Y8dx0iFaCU8nqD/0q6xJf
+fs2euwMEPsHWmA1WwGwxZpE/NGEksMSQ8TZSQUwCsURxBIiGww5MBtIGeO3ZzreR
+Dn0Qhivbiup8ZPtPfFFomoK7ZtWjtGjZ8I5zyYbjT0eEB7P348dkpOtReWDiqGVd
+taMnVau4OTDqTRo6fvAiVb37zoaWETsPWtq/TymgkqO/LEhzClzG8xJgpSl98cQW
+BoHz5GDVYeVxPEKAN4DdS7gt0KTUC9ZQUcZP+1wTzFohDd/CeUAl4kTeP0QSJVJ3
+QC/WnHk4Y56q8/nngIY6w/wID/R/Cp+plw6F5w==
+=BA1F
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/mds.scm b/tests/openpgp/mds.scm
new file mode 100755
index 0000000..50761d0
--- /dev/null
+++ b/tests/openpgp/mds.scm
@@ -0,0 +1,69 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-environment)
+
+(define empty-string-hashes
+ `((1 "D41D8CD98F00B204E9800998ECF8427E" "MD5")
+ (2 "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709" "SHA1")
+ (3 "9C1185A5C5E9FC54612808977EE8F548B2258D31" "RIPEMD160")
+ (11 "D14A028C2A3A2BC9476102BB288234C415A2B01F828EA62AC5B3E42F" "SHA224")
+ (8 "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855" "SHA256")
+ (9 "38B060A751AC96384CD9327EB1B1E36A21FDB71114BE07434C0CC7BF63F6E1DA274EDEBFE76F65FBD51AD2F14898B95B" "SHA384")
+ (10
+ "CF83E1357EEFB8BDF1542850D66D8007D620E4050B5715DC83F4A921D36CE9CE47D0D13C5D85F2B0FF8318D2877EEC2F63B931BD47417A81A538327AF927DA3E"
+ "SHA512")))
+
+(define abc-hashes
+ `((1 "C3FCD3D76192E4007DFB496CCA67E13B" "MD5")
+ (2 "32D10C7B8CF96570CA04CE37F2A19D84240D3A89" "SHA1")
+ (3 "F71C27109C692C1B56BBDCEB5B9D2865B3708DBC" "RIPEMD160")
+ (11 "45A5F72C39C5CFF2522EB3429799E49E5F44B356EF926BCF390DCCC2" "SHA224")
+ (8 "71C480DF93D6AE2F1EFAD1447C66C9525E316218CF51FC8D9ED832F2DAF18B73" "SHA256")
+ (9 "FEB67349DF3DB6F5924815D6C3DC133F091809213731FE5C7B5F4999E463479FF2877F5F2936FA63BB43784B12F3EBB4" "SHA384")
+ (10 "4DBFF86CC2CA1BAE1E16468A05CB9881C97F1753BCE3619034898FAA1AABE429955A1BF8EC483D7421FE3C1646613A59ED5441FB0F321389F77F48A879C7B1F1" "SHA512")))
+
+;; Symbolic names for the triples above.
+(define :algo car)
+(define :value cadr)
+(define :name caddr)
+
+;; Test whether HASH matches REF.
+(define (test-hash hash ref)
+ (unless (eq? #f ref)
+ (if (not (string=? (:value hash) (:value ref)))
+ (fail "failed"))))
+
+;; Test whether the hashes computed over S match the REFERENCE set.
+(define (test-hashes msg s reference)
+ (for-each-p'
+ msg
+ (lambda (hash) (test-hash hash (assv (:algo hash) reference)))
+ (lambda (hash)
+ (let ((ref (assv (:algo hash) reference)))
+ (if (eq? #f ref)
+ (string-append "no-ref-for:" (number->string (:algo hash)))
+ (:name ref))))
+ (gpg-hash-string '(--print-mds) s)))
+
+(test-hashes "Hashing the empty string"
+ "" empty-string-hashes)
+(test-hashes "Hashing the string \"abcdefghijklmnopqrstuvwxyz\""
+ "abcdefghijklmnopqrstuvwxyz" abc-hashes)
diff --git a/tests/openpgp/mkdemodirs b/tests/openpgp/mkdemodirs
new file mode 100755
index 0000000..fd8a741
--- /dev/null
+++ b/tests/openpgp/mkdemodirs
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+set -e
+
+# We need to use --no-options so that a gpg.conf from an older version
+# of gpg is not used.
+GPG="../../g10/gpg --no-options --batch --quiet
+ --no-secmem-warning --allow-secret-key-import"
+
+NAMES='Alpha Bravo Charlie Delta Echo Foxtrot Golf Hotel India
+ Juliet Kilo Lima Mike November Oscar Papa Quebec Romeo
+ Sierra Tango Uniform Victor Whisky XRay Yankee Zulu'
+
+if [ "$1" = "--clean" ]; then
+ (for i in $NAMES; do
+ [ -d $i ] && rm -r $i
+ done) || true
+ exit 0
+fi
+
+$GPG --dearmor -o secdemo.gpg --yes ../checks/secdemo.asc
+$GPG --dearmor -o pubdemo.gpg --yes ../checks/pubdemo.asc
+[ -f ./tdb.tmp ] && rm ./tdb.tmp
+GPGDEMO="$GPG --homedir . --trustdb-name ./tdb.tmp --no-default-keyring
+ --keyring pubdemo.gpg --secret-keyring secdemo.gpg"
+echo -n "Creating:"
+for name in $NAMES; do
+ echo -n " $name"
+ [ -d $name ] && rm -r $name
+ mkdir $name
+ $GPGDEMO --export-secret-key -o - $name > $name/Secret.gpg
+ $GPG --homedir $name --import $name/Secret.gpg
+ $GPGDEMO --export -o - $name > $name/Public.gpg
+ $GPG --homedir $name --import $name/Public.gpg
+ [ -f $name/pubring.gpg~ ] && rm $name/pubring.gpg~
+done
+echo "."
+[ -f ./tdb.tmp ] && rm ./tdb.tmp
+rm pubdemo.gpg secdemo.gpg
+
+
diff --git a/tests/openpgp/multisig.scm b/tests/openpgp/multisig.scm
new file mode 100755
index 0000000..75682eb
--- /dev/null
+++ b/tests/openpgp/multisig.scm
@@ -0,0 +1,169 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+;; Check that gpg verifies only signatures where there is no ambiguity
+;; in the order of packets. Needs the Demo Keys Lima and Mike.
+;;
+;; Note: We do not support multiple signatures anymore thus this test is
+;; not really needed because verify could do the same. We keep it anyway.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(define sig-1ls1ls-valid "
+-----BEGIN PGP ARMORED FILE-----
+
+kA0DAAIRN8q1H7eRA/gBrCdiBXRleHQxOogq9EkgYW0gc29ycnksIEkgY2FuJ3Qg
+ZG8gdGhhdAqIPwMFADqIKvQ3yrUft5ED+BEC2joAoJaSaXOZEtSZqQ780HIXG77e
+8PB7AJ4wCprmaFTO0fBaTcXDuEOBdAWnOZANAwACETfKtR+3kQP4AawnYgV0ZXh0
+MTqIKvRJIGFtIHNvcnJ5LCBJIGNhbid0IGRvIHRoYXQKiD8DBQA6iCr0N8q1H7eR
+A/gRAto6AKCWkmlzmRLUmakO/NByFxu+3vDwewCeMAqa5mhUztHwWk3Fw7hDgXQF
+pzk=
+=8jSC
+-----END PGP ARMORED FILE-----
+")
+(define sig-ls-valid "
+-----BEGIN PGP ARMORED FILE-----
+
+rCdiBXRleHQxOogrS0kgYW0gc29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqI
+K0s3yrUft5ED+BECLQMAn2jZUNOpB4OuurSQkc2TRfg6ek02AJ9+oJS0frQ+yUsT
+QDUFTH2PvZRxjw==
+=J+lb
+-----END PGP ARMORED FILE-----
+")
+(define sig-sl-valid "
+-----BEGIN PGP ARMORED FILE-----
+
+iD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeDrrq0kJHNk0X4OnpNNgCffqCU
+tH60PslLE0A1BUx9j72UcY+sJ2IFdGV4dDE6iCtLSSBhbSBzb3JyeSwgSSBjYW4n
+dCBkbyB0aGF0Cg==
+=N9MP
+-----END PGP ARMORED FILE-----
+")
+(define sig-11lss-valid-but-is-not "
+-----BEGIN PGP ARMORED FILE-----
+
+kA0DAAIRN8q1H7eRA/gAkA0DAAIRN8q1H7eRA/gBrCdiBXRleHQxOogyXUkgYW0g
+c29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqIMl03yrUft5ED+BECwQAAnRXT
+mXjVd385oD38W80XuheWKTGcAJ9pZ6/flaKDfw+SLido7xaUHuhp5Yg/AwUAOogy
+XTfKtR+3kQP4EQLBAACgnN0IP+NztE0aAc/DZ17yHWR9diwAniN0P01WmbgZJoZB
+Q341WRXKS/at
+=Ekrs
+-----END PGP ARMORED FILE-----
+")
+(define sig-11lss11lss-valid-but-is-not "
+-----BEGIN PGP ARMORED FILE-----
+
+kA0DAAIRN8q1H7eRA/gAkA0DAAIRN8q1H7eRA/gBrCdiBXRleHQxOogyXUkgYW0g
+c29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqIMl03yrUft5ED+BECwQAAnRXT
+mXjVd385oD38W80XuheWKTGcAJ9pZ6/flaKDfw+SLido7xaUHuhp5Yg/AwUAOogy
+XTfKtR+3kQP4EQLBAACgnN0IP+NztE0aAc/DZ17yHWR9diwAniN0P01WmbgZJoZB
+Q341WRXKS/atkA0DAAIRN8q1H7eRA/gAkA0DAAIRN8q1H7eRA/gBrCdiBXRleHQx
+OogyXUkgYW0gc29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqIMl03yrUft5ED
++BECwQAAnRXTmXjVd385oD38W80XuheWKTGcAJ9pZ6/flaKDfw+SLido7xaUHuhp
+5Yg/AwUAOogyXTfKtR+3kQP4EQLBAACgnN0IP+NztE0aAc/DZ17yHWR9diwAniN0
+P01WmbgZJoZBQ341WRXKS/at
+=P1Mu
+-----END PGP ARMORED FILE-----
+")
+(define sig-ssl-valid-but-is-not "
+-----BEGIN PGP ARMORED FILE-----
+
+iD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeDrrq0kJHNk0X4OnpNNgCffqCU
+tH60PslLE0A1BUx9j72UcY+IPwMFADqIK0s3yrUft5ED+BECLQMAn2jZUNOpB4Ou
+urSQkc2TRfg6ek02AJ9+oJS0frQ+yUsTQDUFTH2PvZRxj6wnYgV0ZXh0MTqIK0tJ
+IGFtIHNvcnJ5LCBJIGNhbid0IGRvIHRoYXQK
+=Zven
+-----END PGP ARMORED FILE-----
+")
+(define sig-1lsls-invalid "
+-----BEGIN PGP ARMORED FILE-----
+
+kA0DAAIRN8q1H7eRA/gBrCdiBXRleHQxOogq9EkgYW0gc29ycnksIEkgY2FuJ3Qg
+ZG8gdGhhdAqIPwMFADqIKvQ3yrUft5ED+BEC2joAoJaSaXOZEtSZqQ780HIXG77e
+8PB7AJ4wCprmaFTO0fBaTcXDuEOBdAWnOawnYgV0ZXh0MTqIK0tJIGFtIHNvcnJ5
+LCBJIGNhbid0IGRvIHRoYXQKiD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeD
+rrq0kJHNk0X4OnpNNgCffqCUtH60PslLE0A1BUx9j72UcY8=
+=nkeu
+-----END PGP ARMORED FILE-----
+")
+(define sig-lsls-invalid "
+-----BEGIN PGP ARMORED FILE-----
+
+rCdiBXRleHQxOogrS0kgYW0gc29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqI
+K0s3yrUft5ED+BECLQMAn2jZUNOpB4OuurSQkc2TRfg6ek02AJ9+oJS0frQ+yUsT
+QDUFTH2PvZRxj6wnYgV0ZXh0MTqIK0tJIGFtIHNvcnJ5LCBJIGNhbid0IGRvIHRo
+YXQKiD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeDrrq0kJHNk0X4OnpNNgCf
+fqCUtH60PslLE0A1BUx9j72UcY8=
+=BlZH
+-----END PGP ARMORED FILE-----
+")
+(define sig-lss-invalid "
+-----BEGIN PGP ARMORED FILE-----
+
+rCdiBXRleHQxOogrS0kgYW0gc29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqI
+K0s3yrUft5ED+BECLQMAn2jZUNOpB4OuurSQkc2TRfg6ek02AJ9+oJS0frQ+yUsT
+QDUFTH2PvZRxj4g/AwUAOogrSzfKtR+3kQP4EQItAwCfaNlQ06kHg666tJCRzZNF
++Dp6TTYAn36glLR+tD7JSxNANQVMfY+9lHGP
+=jmt6
+-----END PGP ARMORED FILE-----
+")
+(define sig-slsl-invalid "
+-----BEGIN PGP ARMORED FILE-----
+
+iD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeDrrq0kJHNk0X4OnpNNgCffqCU
+tH60PslLE0A1BUx9j72UcY+sJ2IFdGV4dDE6iCtLSSBhbSBzb3JyeSwgSSBjYW4n
+dCBkbyB0aGF0Cog/AwUAOogrSzfKtR+3kQP4EQItAwCfaNlQ06kHg666tJCRzZNF
++Dp6TTYAn36glLR+tD7JSxNANQVMfY+9lHGPrCdiBXRleHQxOogrS0kgYW0gc29y
+cnksIEkgY2FuJ3QgZG8gdGhhdAo=
+=phBF
+-----END PGP ARMORED FILE-----
+")
+
+(for-each-p
+ "Checking that a valid signature is verified as such"
+ (lambda (armored-file)
+ (tr:do
+ (tr:pipe-do
+ (pipe:echo (eval armored-file (current-environment)))
+ (pipe:spawn `(,@GPG --dearmor)))
+ (tr:spawn "" `(,@GPG --verify **in**))))
+ '(sig-sl-valid))
+
+;; ???
+;;
+;; #for i in "$sig-11lss-valid-but-is-not" "$sig-11lss11lss-valid-but-is-not" \
+;; # "$sig-ssl-valid-but-is-not"; do
+;; # echo "$i" | $GPG --dearmor >x
+;; # $GPG --verify <x 2>/dev/null || error "valid is invalid"
+;; #done
+
+(for-each-p
+ "Checking that an invalid signature is verified as such"
+ (lambda (armored-file)
+ (lettmp (file)
+ (pipe:do
+ (pipe:echo (eval armored-file (current-environment)))
+ (pipe:spawn `(,@GPG --dearmor))
+ (pipe:write-to file (logior O_WRONLY O_CREAT O_BINARY) #o600))
+
+ (if (= 0 (call `(,@GPG --verify ,file)))
+ (fail "Bad signature verified ok"))))
+ '(sig-1ls1ls-valid sig-ls-valid sig-1lsls-invalid
+ sig-lsls-invalid sig-lss-invalid sig-slsl-invalid))
diff --git a/tests/openpgp/plain-1-pgp.asc b/tests/openpgp/plain-1-pgp.asc
new file mode 100644
index 0000000..9a83dcf
--- /dev/null
+++ b/tests/openpgp/plain-1-pgp.asc
@@ -0,0 +1,27 @@
+This is an encrypted version of plain-1 for the PGP test key
+0xCB879DE9 using 3DES.
+
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v1.3.5-cvs (GNU/Linux)
+
+hM4DW3oC8MuHnekQAv0U6qlDAA64QS/oZJErr1J77m5Dh7IFen3mAcwOxvL/POqS
+HQWTFcuFT4LH9asSWgRe6DebJGfscMjMqNPAkhEJtKQQ2jEesn2Bon6SMwah7vkD
+9Zap7WKHRlnB/Da1/xQC/ispXY7e5tuejnzoNSAOWFpBn354nvkKGaCfMRNuz3R2
+HljH+gXKRa00n2dPmvX9Mr8AI0Q+FoEI2/YW+6aUxmv8b0c2dP6HcL6HUu0Ro2Nl
+RJNPfYXP20EL/Xrv8LN0Ksnp3YKTWrz5gQKNr3DH5pn1PjFqAKz4JD6rQBpnlh1c
+03gLB1OAJWA6+/QNaEQV451GBZW3ul10R/6621/kk0Isdxn/htlD4Jl/jAvFdlQW
+ULBu1HorZZ5X/IMuMRFwSQkx+H8i0zq+LGr8+rLFVTRuXBrgpeTLWs/f35DDblPp
+jtPGSs1qql98PfOV1tAr16rGRLAAyNWEgi3yZWUGgq5dfFnRbJX1hrj9waQmq1g0
+mn1oB9Ig708xSZqcfFVFNpvIB7nmbFF/WaMnqfL3XmgTe8whKB/f/XYhg+W2d57h
+EmTcAlC1N6IHY8/7YqtnjitavTIUsi0hPldX0tvrjsaZ7ppSma2epRJhx47jIFjw
+wXOEByZE+K3pyTSN8KJxParDsqrTWFrL0t8az9W8lWG7YYsxUxk9cwRo5PyEko1M
+kAKrbDMb+02Iw35yeuxFY33dl7KqpaWy43ksX/ROxX4S0InQywaQejXyt5A1cJN1
+t+G0aKdRp40MDKtOkZfFGlUSFZIhB0dxKVfSKJE/SIeYZzROTuyCNe/2wwufxgpa
+uztUf5ipVnINupiztWGw5c5Wp40ptQ/0K4/35KrZhMoFGR9DtImAPpZocuiFdJDt
+uqqapxGfJ876S4hFjRAkHSNRsAySul9zFLnIJ+Smk5xsvQZK4yjDwZfSs9b7WPKg
+7NCxl5bF5dIbWRYdRBNjHQ4m3LyYmqKzQqALSYT54/9O35B7rb1fOB2SFIuME0QI
+5XQq9QsH/f5rW8U6Ixzw1582B8fO1TMRhCqMyXozmsBJoWdCIQTQiVNyrbgLi+ss
+wKiKq4AymLXFMSpI4TOCc+rKiAdMpLbNO8Ndox5hZEGz+mqg84cgC/rkJc/P03KR
+uo0+rb5eSfJw9t+uzBXDmFHynayj0CB8wW9iwXknpdlHDo1z
+=7Otr
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/plain-1.asc b/tests/openpgp/plain-1.asc
new file mode 100644
index 0000000..f62fb15
--- /dev/null
+++ b/tests/openpgp/plain-1.asc
@@ -0,0 +1,26 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v1.3.5-cvs (GNU/Linux)
+
+hQEOA6urKKJHvid1EAQA0MchGc7vZsjUgxdII4lo/2jRDesMmLDN4U0uOgExvyhD
+u1OtQBJF8iHgNdDEf8/R3GWhRE94IpVwLqzKTqfVmyKIFd80/Qe4h37TUPpEf8Ex
+f7WaIBk/9OSDNKOkCwZ5OH9xGaorhBwYiTNJlEEGv5zcDte9ZoLO7WhWFfHp3b0E
+AJYk/tf3oV4sJSn8AbUa8UC2tAdpNM1Lx+UEuCtxevYRpWeDVDok7/xuaa/wcb39
+lKyhUV+FBUH++k59K4GVqykOz02hmFl97O+4bAldgP6cVTm0Gh7jwMcJANzhLW/O
+MR5birB+HPKOotMIfhggzxsAt6ESrviIlknkGqwKXWog0ukB/npOqQdu1GmvJqoC
+k6ElA6xZPY5HTF/JLKlLXFfIIKLeuyckKwGDkVNFE7JYPW+dfxcGH9z1KXaNNllY
+V4OKGQh3+gMaoJSY2X7PsmjC4fvi3g6rr360ATr5f82Mr8GPa3x21XLdIFZ04vTe
+yE3kwdcarkiT1QQLnOXk/yRBxJwiA5loL9crVdC2WyOV3B3DG33/yas8krw4BYWw
+DzAgxNtZR4MQXcj83WwoflMo43dYUq3Pk7ZnzKN04O8m9w0gxVxCpXu4ds9emMdJ
+WS4eNTPUOnzeWttkfYcd3SarK6COi9iBosFT2QF80FwDSlH3XdEo7rD1j6WJ5GeX
+RbHDvIm9g0xB23S7jmtfdqIHndvPKLmwW2B1VC1mbjcDUo6pyUb31GBd1zFVhT69
+ijhiEwBlr8uWxROdwJd/7IVIB/RYHLr5P3M8p08hdEdS1IMQbNEE4Y25fRdcc6g8
+fVEAExbG01K1EJhRLxoHzgnAkxDTV2HSwlqbFvKEzUfE+rMHApmSX2lfMvKgueYz
+JpA7nxuf79Wk17bjNvuVQwokhXpzw7FyPPdD7h4Z30LW0ozvSVgs2tigWCAysIKB
+3ZIolchqBoj0ddJgbPXrx09r1oCckEmdj1KtZsci9m+CFA8d22uxXBec0HkEHZpr
+EHlqEZfNTmqowoDtJ8KT+S8VPsALEyDnrqm3s4i44OwgvsPiKOST1xwk6lIJ5isu
+fO76RHTQ2jc8z7+sKyNffVugfjYVRj54/8Gj34QkrVo/42rlvg398tpbAbWuNq8w
+PM//M6eVD4IRDYEGrGOk7prd9mgdbWnOWpasirhr41kePu2vsrIUkJWHmOgdMQDH
+cSSzI8C5NpafROHAhMsUymcJ5dKksvPubh5IAdgtH+m6yDnNUJT8s6WV1f1RpSsQ
+L/n3dhti76l0XtfZ7aST8j46B1JPNDx8+r6Xl9IUbSU=
+=xK46
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/plain-1o.asc b/tests/openpgp/plain-1o.asc
new file mode 100644
index 0000000..973b293
--- /dev/null
+++ b/tests/openpgp/plain-1o.asc
@@ -0,0 +1,28 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GNUPG v0.3.4 (GNU/Linux)
+Comment: Get GNUPG from ftp://ftp.guug.de/pub/gcrypt/
+Comment: Use "gpgm --dearmor" for unpacking
+
+PCEtLSBEaWVzIGlzdCBTZWl0ZSAzLCBkb3J0IGlzdCBrZWluZSBTZWl0ZW56YWhsIGFuZ2Vn
+ZWJlbiwKICAgICBvYmVuIHJlY2h0cyBpc3Qgd2llZGVyIGRlciBTdGVtcGVsIHZvbiBtZWlu
+ZW0gT3BhIHp1IGZpbmRlbiAtLT4KCjxzZWN0MT5OYW1lIDxxPkdyb98tQmFydGxvZmY8Lz4K
+CjxwPgpEZXIgTmFtZSA8cS9CYXJ0bG9mZi8gaXN0IHNjaHdlciB6dSBkZXV0ZW4uIE1hbiBo
+YXQgdmllbGUgTXV0bWHfdW5nZW4KYW5nZXN0ZWxsdCwgdm9uIGRlbmVuIG1hbiBhYmVyIGJp
+c2xhbmcga2VpbmUgZWluemlnZSBhbHMgdW5iZWRpbmd0CnJpY2h0aWcgZXJrbORyZW4ga2Fu
+bi4KPGZvbnRpbmZvIHJlbT0ibWl0IExlZXJ6ZWljaGVuIGdlc2NocmllYmVuIj5Vcmt1bmRs
+aWNoPC8+IHdpcmQgZGFzCkRvcmYgYmlzIHp1ciBSZWZvcm1hdGlvbiBzdGV0cyA8cS9CYXJ0
+b3JmLyAoYW5ubyAxMjUzKSB1bmQKPHEvQmFyZG9yZi8gKDEzMDYsIDEzMTgsIDEzMjksIDE0
+MjkpIGdlbmFubnQgdW5kIGRhc18gc293b2hsIEtsZWluLQp3aWUgR3Jv32JhcnRsb2ZmLiBF
+cnN0IDE1ODYgaW0gQmlzY2hvZnNzdGVpbmVyIEp1cmlzZGlrdGlvbmFsYnVjaApoZWnfdCB1
+bnNlciBEb3JmIDxxL0JhcnR0ZWxvZmYvIHVuZCBzbyBhdWNoIGluIGRlciDkbHRlc3RlbiBu
+b2NoCnZvcmhhbmRlbmVuIEtpcmNoZW5yZWNobnVuZyB2b20gSmFocmUgMTY1MS4gTkFjaCBk
+ZW0gSmFocmUgMTcwMCB3aXJkCmluIGRlbiBVcmt1bmRlbiBiZWdvbm5lbiwgZGVuIHZvbGxl
+biBOYW1lbiA8cS9Hcm/fLUJhcnRsb2ZmLyB1bmQKPHEvS2xlaW4tQmFydGxvZmYvIHp1IHNj
+aHJlaWJlbi4KLS0tLS0tLS0tLS0tLS0tLSBbd2VnZW4gZGFzaGVkIGVzY2FwZWQgdGV4dF0K
+PHA+Ck5pbW10IG1hbiBhbiwgZGHfIGRpZSB1cmt1bmRsaWNoZSwg5Gx0ZXN0ZSBCZXplaWNo
+bnVuZyBCYXJ0b3JmIGRpZQp1cnNwcvxuZ2xpY2hlIGlzdCB1bmQgbmljaHQgZGllIG11bmRh
+cnRsaWNoZSBCYXJ0bG9mZiwgc28ga/ZubnRlIGRlcgpOYW1lIGd1dCBnZWRldXRldCB3ZXJk
+ZW4gYWxzIERvcmYgYW4gZGVyIDxxL0JvcmRlLyBvZGVyIGFtIFJhbmRlCm9kZXIgYW4gZGVy
+IEdyZW56ZSBlbnR3ZWRlciBkZXMgV2FsZGVzCg==
+=m1k/
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/plain-2.asc b/tests/openpgp/plain-2.asc
new file mode 100644
index 0000000..5a774a6
--- /dev/null
+++ b/tests/openpgp/plain-2.asc
@@ -0,0 +1,31 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v1.3.5-cvs (GNU/Linux)
+
+hQEOA6urKKJHvid1EAP/aYXFOkxPzbBB0SWtyX+yyvZso8i1WJS3pzrHNXcXQSQx
+xOAfmlCiuXYrjEzlyDAn7k7RLAhUB/ffI58HnbkQ7btWujrHig/V1tQ0j5igR85M
+3y2/msWu2c2pyeZnx29LzeoJ2aMVTbMObszlG+TNOuhCNn4unvbShrkFjNK5fi8E
+AIHiavE77ZPfcaUrXp6FJ6OuhbnJQ8y8CVpH++ddgU6xXK1vByMSsYqiOjfq08gV
+MzqT1eMVvKhSjl3R6Ktl7j+ErYM4KuIofIZsKc8M3JnoTSrLqWSEBq+DEiaSI58i
+SMJfzxfKA84bpJyLIjp4bjRIXveYoX8UjEnSNr3xuDIq0ukBoVe6Bx8lBActcwE+
+kE7EffSBHUmnm8cvwZan+Ms8t9p9aQEzBxV/LfEXZyk36lK35zCH188iJR+tt9zs
+rNubkRuOjq9jAcBtrvgjTTO91Ru7z4RCYeMfnX9AauJZFShBNYN46GTIwqMWE9vq
+B/IYFH9/L2nufcrDQ6u5WxJo0y2FoPqVS4RKEZ4FlKnlT2Op0X1k9w+1nWTtKwQx
+fPsB+YRSKmVbZOXDeKAIVEyGHgR1Hj6pbo/IeHSJ2DJt5OFu6eLQYjxYjM7BPjPD
+Gn+lTUvqw5ykYpCcnvpEx25+qHh5HI11Hi0sLKzvB92hhsQ7+lU2D+iAzsMJKdwE
+u2bCnrZokzZwDBy6NISQ+hoc6NPPezQM4FLN0BB752fa9DYMQo5nEGfPUM7fv51A
+nUdGOmaDVWY54GQxiYzl0JAT41sQSYlVHcWBCGNAm064y+tsHVjDYcf5uze/3Iuw
+m/IbRGLBT7x+j2OqMX30yXoeHCg0/M/2c6vIzhdHEsJjTbTr+M4bMii/mB5kSo/7
+x5R14Lr0mwnPNDFHG2egqd5uL8985+5BENm7q0pQHKGM5NxkjVSWCpzRgKcSEq5A
+x4Q2HbhEJNP6ZonnZkDmGM52Eq62eaR7t8+k9px35osfiTiClmVrjsTgl5Kvatk0
+oL1aYEwp8OtavoSwidUTk+Xb+cEE09P5bnCFs5Js0e5wdo+/izJ6iBuF+PndTh4i
+4ppFmt8/GZ63MKBJu4CZE7QJMVAcmmCrsGRONP2JVgmyaBjrIl5xk9FPXQVY0AJx
+gl3/jO/QFHYs+dlrQ3aqg8Mm0eZyLmZEYjoNibD8PW0keYiVfTF7EGl4jS2sAboc
+AOzbuABa+30vIjJRWeW5UdTcLyNK7B2qWk6dqpRn9ps3cwCWUiTIcIRgot4PY+3M
+8BL4smyZIP1Fmz/woL7gSVIaJHMExHjYPyRlfo+6Vfy3hh3zdiB9e5xA8QRFKgUb
+Px5ShU5bBykfvFBJjgKU1XLBKqdklaudf3+v8F3LPIyuO6vTYzOIU9UKAHy9CrA2
+kAZ8kgHBTtAjmKuJjASBCZHPepq0G9SaRDQI5g4DXx0LXPX3y5xkwVI6kd0QmsMF
+UU4ij/xjzIPN/AxBgQI8HKk56FnaX0JKoHm7mqWa+1TzbuvJjio4J/IN9XXzVqb1
+YL+mkx607hdW9oJltXLO5eio0pb12v/0YXAQlsrlJJNPCUW5hYFv/vH1rHzR98xx
+nx4PXElm8VUuhKDxdVi9Ipo8fL9Amu3PwYonzOck3R2W4wwlmcopVQQ=
+=Ng8B
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/plain-2o.asc b/tests/openpgp/plain-2o.asc
new file mode 100644
index 0000000..562e5f0
--- /dev/null
+++ b/tests/openpgp/plain-2o.asc
@@ -0,0 +1,36 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GNUPG v0.3.4 (GNU/Linux)
+Comment: Get GNUPG from ftp://ftp.guug.de/pub/gcrypt/
+Comment: Use "gpgm --dearmor" for unpacking
+
+Cgo8c2VjdD5Wb3J3b3J0CjxwPgpEZXIgV2VydCBlaW5lciBPcnRzY2hyb25payBpc3Qgb2Zm
+ZW5iYXIgdW5kIGJlZGFyZiBrZWluZXIgRXL2cnRlcnVuZy4KTWl0IEF1c2JydWNoIGRlcyBX
+ZWx0a3JpZWdlc18sIGlubWl0dGVuIGRlciBnZXdhbHRpZ2VuIEdlc2NoZWhuaXNzZSwgZvxo
+bHRlCmRlciBLbGVydXNfIHVuc2VyZXNfIEVpY2hzX2ZlbGRlc18gZGFzXyBtZWhyIHdpZSBm
+cvxoZXIgdW5kIHNvCmVyc3Rhcmt0ZSBkYXNfIFN0cmViZW4sIGVpbmUgc29sY2hlIE9ydHNf
+Z2VzY2hpY2h0ZSB6dSBzY2FoZmZlbiwgdW0KdW5zZXJlbiBOYWNoa29tbWVuIHp1IGJlcmlj
+aHRlbiwgd2FzXyBhdWNoIGRpZSBrbGVpbnN0ZW4gRPZyZmVyIGluCmRlciBncm/fZW4gWmVp
+dCBnZWxlaXN0ZXQsIGVybGVidCB1bmQgZXJsaXR0ZW4gaGFiZW4uCjxwPgpVbmQgc28gYmVn
+YW5uIGF1Y2ggaWNoIGltIERlemVtYmVyIDE5MTQsIGRlbiA/Pz8/Pz8/Pz8KU3RvZmYsIHdv
+IGltbWVyIGljaCBpaG4gYXVjaCBudXIgc28gc3DkcmxpY2ggZmluZGVuIGtvbm50ZSwgenUK
+c2FtbWVsbiwgaWNoIGJlZnJhZ3RlIHp1buRjaHN0IGVtc2lnIGRpZSDkbHRlc3RlbiBMZXV0
+ZSwKZHVyY2hmb3JzY2h0ZSBzb2Rhbm4gZGFzIGdhbnplIFBmYXJyYXJjaGl2LCBkYXMgU2No
+dWx6ZW5hcmNoaXYKYmVpZGVyIFBmYXJyZPZyZmVyLCBkYXMgS29tbWlzc2FyaWF0c19hcmNo
+aXYgenUgSGVpbGlnZW5zdGFkdCwKZW5kbGljaCBhdWNoIDE5MTYgZGFzIFN0YWF0c19hcmNo
+aXYgenUgTWFnZGVidXJnLiBTZWxic3R2ZXJzdORuZGxpY2gKYXJiZWl0ZXRlIGljaCBhdWNo
+IGRpZSBlaW5zY2hs5GdpZ2UgTGl0ZXJhdHVyIGR1cmNoLiBHYXIgdmllbGUgWmVpdAp1bmQg
+TfxoZSBoYXQgZXNfIGdla29zdGV0IHVtIG5hY2ggbWVociBhbHMgOCBKYWhyZW4gZGllIE9y
+dHNjaHJvbmlrIHZvbgpHcm/fYmFydGxvZmYgdW5kIHZvbSBGaWxpYWxkb3JmIFdpbGJpY2gg
+Z2Vzb25kZXJ0IHp1IHNjaGFmZmVuLgo8cCB2c3BhY2U9IjJleCI+CjxiZj5Hcm/fYmFydGxv
+ZmYsPC8+IGRlbiAyMy4gTeRyeiAxOTIzLgo8cCB2c3BhY2U9IjNleCIgYWxpZ249cmlnaHQ+
+CjxiZi9OaWtvbGF1cyBH9nJpbmcsLyBQZmFycmVyLgo8L3A+Cgo8IS0tIEhpZXIgZm9sZ3Qg
+ZWluIFN0ZW1wZWwgdm9uIG1laW5lbSBPcGE6CgkgIFJ1ZC4gS29jaAogICAgIEdyb99iYXJ0
+bG9mZi9FaWNoc2ZlbGQKCUFuZ2VyIDE2MQotLT4KPCEtLSBGSVhNRTogaGllciBrb21tdCBl
+aW5lbiBaaWVybGluaWUgLS0+Cgo8cCB2c3BhY2U9ZmlsbD4gPCEtLSBEZXIgUmVzdCBrYW0g
+YW0gRW5kZSBkZXIgU2VpdGUgLS0+CjxwIGFsaWduPWNlbnRlcj4gTGl0ZXJhdHVyOiA8L3A+
+CjEpIEpvaC4gV29sZjogUG9saXRpc2NoZSBHZXNjaGljaHRlIGRlcyBFaWNoc2YuIEf2dHQu
+IDE3OTIgdW5kCkz2ZmZsZXIgMTkyMS4gMikgSy4gR2VzY2hpY2h0ZSwgV29sZiAxODE2IEf2
+dHQuICAzKSBLbmllYjogR2VzY2guCmRlciBSZWYuIHUuIEdlZ2VucmVmPz8/Cgo8IS0tIEZJ
+WE1FOiBEZXIgUmVzdCBmZWhsdCBub2NoIC0tPgoKCgoKCgoKCjwvc2VjdD4K
+=9nnj
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/plain-3.asc b/tests/openpgp/plain-3.asc
new file mode 100644
index 0000000..b2206ae
--- /dev/null
+++ b/tests/openpgp/plain-3.asc
@@ -0,0 +1,13 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v1.3.5-cvs (GNU/Linux)
+
+hQEOA6urKKJHvid1EAQAreXx68NPUPpiNhqRyM//Y97N8hX5iAWq3WxXTa8D6Hy9
+81Jy2wI4IeDhHIoWuXMIX2oVL//V1+LyLkrF/tutBVvqct0TUDUWqb4Ydpfk2l5j
+FfSybWW1fS4D1e0KVB3Lfj2Y4cCoT/+zyq7jUKQE++qNefPBzeaRWY4qeI6xXF8E
+AMj01HPe0ZwIBWqiIYv91Q7rGzEZm0ROPilgSQjUvCdsNQGhZpFGTl6uMSU0lmp8
+SD2EKv3xGeo2nMPy/Xp4JoYAMW+fjJh+wM6uT84nJgCVaeWyR7HAfF1U4rzqz7DF
+amPozuwuZiyjoo/wB1irZSl90t5Oa69oMesZtGMvwBN10mMBM0TotT4gjgviv5uY
+kLjD7DM79xy0drptNypmcVcjnDunM6bSEhTyq/fahdaULTYcwSOTXVMyesNpmLCb
+ziayleyuSaXPxIqWTgSfkab/W2FGWZvbexYaSaWXmDqsyzs81o0=
+=JDKF
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/plain-3o.asc b/tests/openpgp/plain-3o.asc
new file mode 100644
index 0000000..409b9c2
--- /dev/null
+++ b/tests/openpgp/plain-3o.asc
@@ -0,0 +1,10 @@
+Stored by G10, because diff/patch have problems with
+files not having a trailing LF - and this one has none.
+
+-----BEGIN PGP ARMORED FILE-----
+Version: G10 v0.2.6a (Linux)
+Comment: This is an alpha version!
+
+RGllcyBpc3QgZWluZSBlaW5mYWNoZSBaZWlsZSBvaG5lIExGIGFtIEVuZGUu
+=ZQ6m
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/plain-large.asc b/tests/openpgp/plain-large.asc
new file mode 100644
index 0000000..d81b331
--- /dev/null
+++ b/tests/openpgp/plain-large.asc
@@ -0,0 +1,1332 @@
+-----BEGIN PGP MESSAGE-----
+
+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
+=3L8L
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/plain-largeo.asc b/tests/openpgp/plain-largeo.asc
new file mode 100644
index 0000000..2f14bdd
--- /dev/null
+++ b/tests/openpgp/plain-largeo.asc
@@ -0,0 +1,4205 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+IyBIQUNLSU5HICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+ICAgICAgICAgICAgICAgIC0qLSBvcmcgLSotCiMrVElUTEU6IEEgSGFja2VyJ3Mg
+R3VpZGUgdG8gR251UEcKIytURVhUOiBTb21lIG5vdGVzIG9uIEdudVBHIGludGVy
+bmFscwojK1NUQVJUVVA6IHNob3dhbGwKIytPUFRJT05TOiBeOnt9CgoqIEhvdyB0
+byBjb250cmlidXRlCgogIFRoZSBmb2xsb3dpbmcgc3R1ZmYgZXhwbGFpbnMgc29t
+ZSBiYXNpYyBwcm9jZWR1cmVzIHlvdSBuZWVkIHRvCiAgZm9sbG93IGlmIHlvdSB3
+YW50IHRvIGNvbnRyaWJ1dGUgY29kZSBvciBkb2N1bWVudGF0aW9uLgoKKiogTm8g
+bW9yZSBDaGFuZ2VMb2cgZmlsZXMKCkRvIG5vdCBtb2RpZnkgYW55IG9mIHRoZSBD
+aGFuZ2VMb2cgZmlsZXMgaW4gR251UEcuICBTdGFydGluZyBvbgpEZWNlbWJlciAx
+c3QsIDIwMTEgd2UgcHV0IGNoYW5nZSBpbmZvcm1hdGlvbiBvbmx5IGluIHRoZSBH
+SVQgY29tbWl0CmxvZywgYW5kIGdlbmVyYXRlIGEgdG9wLWxldmVsIENoYW5nZUxv
+ZyBmaWxlIGZyb20gbG9ncyBhdCAibWFrZSBkaXN0Igp0aW1lLiAgQXMgc3VjaCwg
+dGhlcmUgYXJlIHN0cmljdCByZXF1aXJlbWVudHMgb24gdGhlIGZvcm0gb2YgdGhl
+CmNvbW1pdCBsb2cgbWVzc2FnZXMuICBUaGUgb2xkIENoYW5nZUxvZyBmaWxlcyBo
+YXZlIGFsbCBiZSByZW5hbWVkIHRvCkNoYW5nZUxvZy0yMDExCgoqKiBDb21taXQg
+bG9nIHJlcXVpcmVtZW50cwoKWW91ciBjb21taXQgbG9nIHNob3VsZCBhbHdheXMg
+c3RhcnQgd2l0aCBhIG9uZS1saW5lIHN1bW1hcnksIHRoZQpzZWNvbmQgbGluZSBz
+aG91bGQgYmUgYmxhbmssIGFuZCB0aGUgcmVtYWluaW5nIGxpbmVzIGFyZSB1c3Vh
+bGx5CkNoYW5nZUxvZy1zdHlsZSBlbnRyaWVzIGZvciBhbGwgYWZmZWN0ZWQgZmls
+ZXMuICBIb3dldmVyLCBpdCdzIGZpbmUKLS0tIGV2ZW4gcmVjb21tZW5kZWQgLS0t
+IHRvIHdyaXRlIGEgZmV3IGxpbmVzIG9mIHByb3NlIGRlc2NyaWJpbmcgdGhlCmNo
+YW5nZSwgd2hlbiB0aGUgc3VtbWFyeSBhbmQgQ2hhbmdlTG9nIGVudHJpZXMgZG9u
+J3QgZ2l2ZSBlbm91Z2ggb2YKdGhlIGJpZyBwaWN0dXJlLiAgT21pdCB0aGUgbGVh
+ZGluZyBUQUJzIHRoYXQgeW91IGFyZSBzZWVpbmcgaW4gYQoicmVhbCIgQ2hhbmdl
+TG9nIGZpbGUsIGJ1dCBrZWVwIHRoZSBtYXhpbXVtIGxpbmUgbGVuZ3RoIGF0IDcy
+IG9yCnNtYWxsZXIsIHNvIHRoYXQgdGhlIGdlbmVyYXRlZCBDaGFuZ2VMb2cgbGlu
+ZXMsIGVhY2ggd2l0aCBpdHMgbGVhZGluZwpUQUIsIHdpbGwgbm90IGV4Y2VlZCA4
+MCBjb2x1bW5zLiAgSWYgeW91IHdhbnQgdG8gYWRkIHRleHQgd2hpY2ggc2hhbGwK
+bm90IGJlIGNvcGllZCB0byB0aGUgQ2hhbmdlTG9nLCBzZXBhcmF0ZSBpdCBieSBh
+IGxpbmUgY29uc2lzdGluZyBvZgp0d28gZGFzaGVzIGF0IHRoZSBiZWdpbiBvZiBh
+IGxpbmUuCgpUaGUgb25lLWxpbmUgc3VtbWFyeSB1c3VhbGx5IHN0YXJ0cyB3aXRo
+IGEga2V5d29yZCB0byBpZGVudGlmeSB0aGUKbWFpbmx5IGFmZmVjdGVkIHN1YnN5
+c3RlbS4gIElmIG1vcmUgdGhhbiBvbmUga2V5d29yZCBpcyByZXF1aXJlZCB0aGUK
+YXJlIGRlbGltaXRlZCBieSBhIGNvbW1hIChlLmcuID1zY2QsdzMyOj0pLiBDb21t
+b25seSBmb3VuZCBrZXl3b3JkcwphcmUKCiAtIGFnZW50ICAgOjogVGhlIGdwZy1h
+Z2VudCBjb21wb25lbnQKIC0gc3NoICAgICA6OiBUaGUgc3NoLWFnZW50IHBhcnQg
+b2YgdGhlIGFnZW50CiAtIGNvbW1vbiAgOjogQ29kZSBpbiBjb21tb24KIC0gaW9i
+dWYgICA6OiBUaGUgSU9CVUYgc3lzdGVtIGluIGNvbW1vbgogLSBncGcgICAgIDo6
+IFRoZSBncGcgb3IgZ3BndiBjb21wb25lbnRzCiAtIGdwZ3NtICAgOjogVGhlIGdw
+Z3NtIGNvbXBvbmVudAogLSBzY2QgICAgIDo6IFRoZSBzY2RhZW1vbiBjb21wb25l
+bnQKIC0gY2NpZCAgICA6OiBUaGUgQ0NJRCBkcml2ZXIgaW4gc2NkYWVtb24KIC0g
+ZGlybW5nciA6OiBUaGUgZGlybW5nciBjb21wb25lbnQKIC0gdzMyICAgICA6OiBX
+aW5kb3dzIHJlbGF0ZWQgY29kZQogLSBwbyAgICAgIDo6IFRyYW5zbGF0aW9ucwog
+LSBidWlsZCAgIDo6IENoYW5nZXMgdG8gdGhlIGJ1aWxkIHN5c3RlbQogLSBzcGVl
+ZG8gIDo6IFNwZWVkbyBidWlsZCBzeXN0ZW0gc3BlY2lmaWMgY2hhbmdlcwogLSBk
+b2MgICAgIDo6IERvY3VtZW50YXRpb24gY2hhbmdlcwoKVHlwbyBmaXhlcyBhbmQg
+ZG9jdW1lbnRhdGlvbiB1cGRhdGVzIGRvbid0IG5lZWQgYSBDaGFuZ2VMb2cgZW50
+cnk7CnRodXMgeW91IHdvdWxkIHVzZSBhIGNvbW1pdCBtZXNzYWdlIGxpa2UKCiMr
+YmVnaW5fZXhhbXBsZQpGaXggdHlwbyBpbiBhIGNvbW1lbnQKCi0tCiMrZW5kX2V4
+YW1wbGUKClRoZSBtYXJrZXIgbGluZSBoZXJlIGlzIGltcG9ydGFudDsgd2l0aG91
+dCBpdCB0aGUgZmlyc3QgbGluZSB3b3VsZAphcHBlYXIgaW4gdGhlIENoYW5nZUxv
+Zy4KCklmIHlvdSBleGNlcHRpb25hbGx5IG5lZWQgdG8gaGF2ZSBsb25nZXIgbGlu
+ZXMgaW4gYSBjb21taXQgbG9nIHlvdSBtYXkKZG8gdGhpcyBhZnRlciB0aGlzIHNj
+aXNzb3IgbGluZToKIytiZWdpbl9leGFtcGxlCiMgLS0tLS0tLS0tLS0tLS0tLS0t
+LS0tLS0tID44IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojK2VuZF9leGFtcGxl
+CihoYXNoLCBibGFuaywgMjQgZGFzaGVzLCBibGFuaywgc2Npc3NvciwgYmxhbmss
+IDI0IGRhc2hlcykuCk5vdGUgdGhhdCBzdWNoIGEgY29tbWVudCB3aWxsIGJlIHJl
+bW92ZWQgaWYgdGhlIGdpdCBjb21taXQgb3B0aW9uCj0tLWNsZWFudXA9c2Npc3Nv
+cj0gaXMgdXNlZC4KCgoqKiBMaWNlbnNlIHBvbGljeQoKICBHbnVQRyBpcyBsaWNl
+bnNlZCB1bmRlciB0aGUgR1BMdjMrIHdpdGggc29tZSBmaWxlcyB1bmRlciBhIG1p
+eGVkCiAgTEdQTHYzKy9HUEx2MisgbGljZW5zZS4gIEl0IGlzIHRodXMgaW1wb3J0
+YW50LCB0aGF0IGFsbCBjb250cmlidXRlZAogIGNvZGUgYWxsb3dzIGZvciBhbiB1
+cGRhdGUgb2YgdGhlIGxpY2Vuc2U7IGZvciBleGFtcGxlIHdlIGNhbid0CiAgYWNj
+ZXB0IGNvZGUgdW5kZXIgdGhlIEdQTHYyKG9ubHkpLgoKICBHbnVQRyB1c2VkIHRv
+IGhhdmUgYSBzdHJpY3QgcG9saWN5IG9mIHJlcXVpcmluZyBjb3B5cmlnaHQKICBh
+c3NpZ25tZW50cyB0byB0aGUgRlNGLiAgVG8gYXZvaWQgdGhpcyBtYWpvciBvcmdh
+bml6YXRpb25hbCBvdmVyaGVhZAogIGFuZCB0byBhbGxvdyBpbmNsdXNpb24gb2Yg
+Y29kZSwgbm90IGNvcHlyaWdodGVkIGJ5IHRoZSBGU0YsIHRoaXMKICBwb2xpY3kg
+aGFzIGJlZW4gcmVsYXhlZCBvbiAyMDEzLTAzLTI5LiAgSXQgaXMgbm93IGFsc28g
+cG9zc2libGUgdG8KICBjb250cmlidXRlIGNvZGUgYnkgYXNzZXJ0aW5nIHRoYXQg
+dGhlIGNvbnRyaWJ1dGlvbiBpcyBpbiBhY2NvcmRhbmNlCiAgdG8gdGhlICJMaWJn
+Y3J5cHQgRGV2ZWxvcGVyJ3MgQ2VydGlmaWNhdGUgb2YgT3JpZ2luIiBhcyBmb3Vu
+ZCBpbiB0aGUKICBmaWxlICJEQ08iLiAgKEV4Y2VwdCBmb3IgYSBzbGlnaHQgd29y
+ZGluZyBjaGFuZ2UsIHRoaXMgRENPIGlzCiAgaWRlbnRpY2FsIHRvIHRoZSBvbmUg
+dXNlZCBieSB0aGUgTGludXgga2VybmVsLikKCiAgSWYgeW91IHdhbnQgdG8gY29u
+dHJpYnV0ZSBjb2RlIG9yIGRvY3VtZW50YXRpb24gdG8gR251UEcgYW5kIHlvdQog
+IGRpZG4ndCBzaWduIGEgY29weXJpZ2h0IGFzc2lnbm1lbnQgd2l0aCB0aGUgRlNG
+IGluIHRoZSBwYXN0LCB5b3UKICBuZWVkIHRvIHRha2UgdGhlc2Ugc2ltcGxlIHN0
+ZXBzOgoKICAtIERlY2lkZSB3aGljaCBtYWlsIGFkZHJlc3MgeW91IHdhbnQgdG8g
+dXNlLiAgUGxlYXNlIGhhdmUgeW91ciByZWFsCiAgICBuYW1lIGluIHRoZSBhZGRy
+ZXNzIGFuZCBub3QgYSBwc2V1ZG9ueW0uICBBbm9ueW1vdXMgY29udHJpYnV0aW9u
+cwogICAgY2FuIG9ubHkgYmUgZG9uZSBpZiB5b3UgZmluZCBhIHByb3h5IHdobyBj
+ZXJ0aWZpZXMgZm9yIHlvdS4KCiAgLSBJZiB5b3VyIGVtcGxveWVyIG9yIHNjaG9v
+bCBtaWdodCBjbGFpbSBvd25lcnNoaXAgb2YgY29kZSB3cml0dGVuCiAgICBieSB5
+b3U7IHlvdSBuZWVkIHRvIHRhbGsgdG8gdGhlbSB0byBtYWtlIHN1cmUgdGhhdCB5
+b3UgaGF2ZSB0aGUKICAgIHJpZ2h0IHRvIGNvbnRyaWJ1dGUgdW5kZXIgdGhlIERD
+Ty4KCiAgLSBTZW5kIGFuIE9wZW5QR1Agc2lnbmVkIG1haWwgdG8gdGhlIGdudXBn
+LWRldmVsQGdudXBnLm9yZyBtYWlsaW5nCiAgICBsaXN0IGZyb20geW91ciBtYWls
+IGFkZHJlc3MuICBJbmNsdWRlIGEgY29weSBvZiB0aGUgRENPIGFzIGZvdW5kCiAg
+ICBpbiB0aGUgb2ZmaWNpYWwgbWFzdGVyIGJyYW5jaC4gIEluc2VydCB5b3VyIG5h
+bWUgYW5kIGVtYWlsIGFkZHJlc3MKICAgIGludG8gdGhlIERDTyBpbiB0aGUgc2Ft
+ZSB3YXkgeW91IHdhbnQgdG8gdXNlIGl0IGxhdGVyLiAgRXhhbXBsZToKCiAgICAg
+IFNpZ25lZC1vZmYtYnk6IEpvZSBSLiBIYWNrZXIgPGpvZUBleGFtcGxlLm9yZz4K
+CiAgICAoSWYgeW91IHJlYWxseSBuZWVkIGl0LCB5b3UgbWF5IHBlcmZvcm0gc2lt
+cGxlIHRyYW5zZm9ybWF0aW9ucyBvZgogICAgdGhlIG1haWwgYWRkcmVzczogUmVw
+bGFjaW5nICJAIiBieSAiIGF0ICIgb3IgIi4iIGJ5ICIgZG90ICIuKQoKICAtIFRo
+YXQncyBpdC4gIEZyb20gbm93IG9uIHlvdSBvbmx5IG5lZWQgdG8gYWRkIGEgIlNp
+Z25lZC1vZmYtYnk6IgogICAgbGluZSB3aXRoIHlvdXIgbmFtZSBhbmQgbWFpbCBh
+ZGRyZXNzIHRvIHRoZSBjb21taXQgbWVzc2FnZS4gIEl0IGlzCiAgICByZWNvbW1l
+bmRlZCB0byBzZW5kIHRoZSBwYXRjaGVzIHVzaW5nIGEgUEdQL01JTUUgc2lnbmVk
+IG1haWwuCgoqKiBDb2Rpbmcgc3RhbmRhcmRzCgogIFBsZWFzZSBmb2xsb3cgdGhl
+IEdOVSBjb2Rpbmcgc3RhbmRhcmRzLiAgSWYgeW91IGFyZSBpbiBkb3VidCBjb25z
+dWx0CiAgdGhlIGV4aXN0aW5nIGNvZGUgYXMgYW4gZXhhbXBsZS4gIERvIG5vIHJl
+LWluZGVudCBjb2RlIHdpdGhvdXQgYQogIG5lZWQuICBJZiB5b3UgcmVhbGx5IG5l
+ZWQgdG8gZG8gaXQsIHVzZSBhIHNlcGFyYXRlIGNvbW1pdCBmb3Igc3VjaCBhCiAg
+Y2hhbmdlLgoKICAtIE9ubHkgY2VydGFpbiBDOTkgZmVhdHVyZXMgbWF5IGJlIHVz
+ZWQgKHNlZSBiZWxvdyk7IGluIGdlbmVyYWwKICAgIHN0aWNrIHRvIEM5MC4KICAt
+IFBsZWFzZSBkbyBub3QgdXNlIEMrKyA9Ly89IHN0eWxlIGNvbW1lbnRzLgogIC0g
+VHJ5IHRvIGZpdCBsaW5lcyBpbnRvIDgwIGNvbHVtbnMuCiAgLSBJZ25vcmUgc2ln
+bmVkL3Vuc2lnbmVkIHBvaW50ZXIgbWlzbWF0Y2hlcwogIC0gTm8gYXJpdGhtZXRp
+YyBvbiB2b2lkIHBvaW50ZXJzOyBjYXN0IHRvIGNoYXIqIGZpcnN0LgogIC0gV2Ug
+dXNlIG91ciBvd24gcHJpbnRmIHN0eWxlIGZ1bmN0aW9ucyBsaWtlID1lc19wcmlu
+dGY9LCBhbmQKICAgID1lc19hc3ByaW50Zj0gd2hpY2ggaW1wbGVtZW50IG1vc3Qg
+Qzk5IGZlYXR1cmVzIHdpdGggdGhlIGV4Y2VwdGlvbgogICAgb2YgPXdjaGFyX3Q9
+ICh3aGljaCBzaG91bGQgYW55d2F5IG5vdCBiZSB1c2VkKS4gIFBsZWFzZSBhbHdh
+eXMgdXNlCiAgICB0aGVtIGFuZCBkbyBub3QgcmVzb3J0IHRvIHRob3NlIHByb3Zp
+ZGVkIGJ5IGxpYmMuICBUaGUgcmF0aW9uYWxlCiAgICBmb3IgdXNpbmcgdGhlbSBp
+cyB0aGF0IHdlIGtub3cgdGhhdCB0aGUgZm9ybWF0IHNwZWNpZmllcnMgd29yayBv
+bgogICAgYWxsIHBsYXRmb3JtcyBhbmQgdGhhdCB3ZSBkbyBub3QgbmVlZCB0byBj
+aGFzZSBwbGF0Zm9ybSBkZXBlbmRlbnQKICAgIGJ1Z3MuCiAgLSBJdCBpcyBjb21t
+b24gdG8gaGF2ZSBhIGxhYmVsIG5hbWVkICJsZWF2ZSIgZm9yIGEgZnVuY3Rpb24n
+cwogICAgY2xlYW51cCBhbmQgcmV0dXJuIGNvZGUuICBUaGlzIGhlbHBzIHdpdGgg
+ZnJlZWluZyBtZW1vcnkgYW5kIGlzIGEKICAgIGNvbnZlbmllbnQgbG9jYXRpb24g
+dG8gc2V0IGEgYnJlYWtwb2ludCBmb3IgZGVidWdnaW5nLgogIC0gQWx3YXlzIHVz
+ZSB4ZnJlZSgpIGluc3RlYWQgb2YgZnJlZSgpLiAgSWYgaXQgaXMgbm90IGVhc3kg
+dG8gc2VlCiAgICB0aGF0IHRoZSBmcmVlZCB2YXJpYWJsZSBpcyBub3QgYW55bW9y
+ZSB1c2VkLCBleHBsaWNpdGx5IHNldCB0aGUKICAgIHZhcmlhYmxlIHRvIE5VTEwu
+CiAgLSBJbml0IGZ1bmN0aW9uIGxvY2FsIHZhcmlhYmxlcyBvbmx5IGlmIG5lZWRl
+ZCBzbyB0aGF0IHRoZSBjb21waWxlcgogICAgY2FuIGRvIGEgYmV0dGVyIGpvYiBp
+biBkZXRlY3RpbmcgdW5pbml0aWFsaXplZCB2YXJpYWJsZXMgd2hpY2ggbWF5CiAg
+ICBpbmRpY2F0ZSBhIHByb2JsZW0gd2l0aCB0aGUgY29kZS4KICAtIE5ldmVyIGlu
+aXQgc3RhdGljIG9yIGZpbGUgbG9jYWwgdmFyaWFibGVzIHRvIDAgdG8gbWFrZSBz
+dXJlIHRoZXkKICAgIGVuZCB1cCBpbiBCU1MuCiAgLSBVc2UgLS1lbmFibGUtbWFp
+bnRhaW5lci1tb2RlIHdpdGggY29uZmlndXJlLgoKKioqIEM5OSBsYW5ndWFnZSBm
+ZWF0dXJlcwoKICBJbiBHbnVQRyAyLngsIGJ1dCAqbm90IGluIDEuNCogYW5kIG5v
+dCBpbiBtb3N0IGxpYnJhcmllcywgYSBsaW1pdGVkCiAgc2V0IG9mIEM5OSBmZWF0
+dXJlcyBtYXkgYmUgdXNlZDoKCiAgLSBWYXJpYWRpYyBtYWNyb3M6CiAgICA6ICNk
+ZWZpbmUgZm9vKGEsLi4uKSAgYmFyKGEsIF9fVkFfQVJHU19fKQoKICAtIFRoZSBw
+cmVkZWZpbmVkIG1hY3JvID1fX2Z1bmNfXz06CiAgICA6IGxvZ19kZWJ1ZyAoIiVz
+OiBQcm9ibGVtIHdpdGggZm9vXG4iLCBfX2Z1bmNfXyk7CgogIC0gVmFyaWFibGUg
+ZGVjbGFyYXRpb24gaW5zaWRlIGEgZm9yKCk6CiAgICA6IGZvciAoaW50IGkgPSAw
+OyBpIDwgNTsgKyspCiAgICA6ICAgYmFyIChpKTsKCiAgQWx0aG91Z2ggd2UgdXN1
+YWxseSBtYWtlIHVzZSBvZiB0aGUgPXUxNj0sID11MzI9LCBhbmQgPXU2ND0gdHlw
+ZXMsCiAgaXQgaXMgYWxzbyBwb3NzaWJsZSB0byBpbmNsdWRlID08c3RkaW50Lmg+
+PSBhbmQgdXNlID1pbnQxNl90PSwKICA9aW50MzJfdD0sID1pbnQ2NF90PSwgPXVp
+bnQxNl90PSwgPXVpbnQzMl90PSwgYW5kID11aW50NjRfdD0uICBCdXQgZG8KICBu
+b3QgdXNlID1pbnQ4X3Q9IG9yID11aW50OF90PS4KCioqIENvbW1pdCBsb2cga2V5
+d29yZHMKCiAgLSBHbnVQRy1idWctaWQgOjogVmFsdWVzIGFyZSBjb21tYSBvciBz
+cGFjZSBkZWxpbWl0ZWQgYnVnIG51bWJlcnMKICAgICAgICAgICAgICAgICAgICBm
+cm9tIGJ1Zy5nbnVwZy5vcmcgcGVydGFpbmluZyB0byB0aGlzIGNvbW1pdC4KICAt
+IERlYmlhbi1idWctaWQgOjogU2FtZSBhcyBhYm92ZSBidXQgZnJvbSB0aGUgRGVi
+aWFuIGJ1ZyB0cmFja2VyLgogIC0gQ1ZFLWlkIDo6IENWRSBpZCBudW1iZXIgcGVy
+dGFpbmluZyB0byB0aGlzIGNvbW1pdC4KICAtIFJlZ3Jlc3Npb24tZHVlLXRvIDo6
+IENvbW1pdCBpZCBvZiB0aGUgcmVncmVzc2lvbiBmaXhlZCBieSB0aGlzIGNvbW1p
+dC4KICAtIEZpeGVzLWNvbW1pdCA6OiBDb21taXQgaWQgdGhpcyBjb21taXQgZml4
+ZXMuCiAgLSBSZXBvcnRlZC1ieSA6OiBWYWx1ZSBpcyBhIG5hbWUgb3IgbWFpbCBh
+ZGRyZXNzIG9mIGEgYnVnIHJlcG9ydGUuCiAgLSBTdWdnZXN0ZWQtYnkgOjogVmFs
+dWUgaXMgYSBuYW1lIG9yIG1haWwgYWRkcmVzcyBvZiBzb21lb25lIGhvdwogICAg
+ICAgICAgICAgICAgICAgIHN1Z2dlc3RlZCB0aGlzIGNoYW5nZS4KICAtIENvLWF1
+dGhvcmVkLWJ5IDo6IE5hbWUgb3IgbWFpbCBhZGRyZXNzIG9mIGEgY28tYXV0aG9y
+CiAgLSBTb21lLWNvbW1lbnRzLWJ5IDo6IE5hbWUgb3IgbWFpbCBhZGRyZXNzIG9m
+IHRoZSBhdXRob3Igb2YKICAgICAgICAgICAgICAgICAgICAgICAgYWRkaXRpb25h
+bCBjb21tZW50cyAoY29tbWl0IGxvZyBvciBjb2RlKS4KICAtIFByb29mcmVhZC1i
+eSA6OiBTb21ldGltZXMgdXNlZCBieSB0cmFuc2xhdGlvbiBjb21taXRzLgogIC0g
+U2lnbmVkLW9mZi1ieSA6OiBOYW1lIG9yIG1haWwgYWRkcmVzcyBvZiB0aGUgZGV2
+ZWxvcGVyCgoqIFdpbmRvd3MKKiogSG93IHRvIGJ1aWxkIGFuIGluc3RhbGxlciBm
+b3IgV2luZG93cwoKICAgWW91ciBiZXN0IGJldCBpcyB0byB1c2UgYSBkZWNlbnQg
+RGViaWFuIFN5c3RlbSBmb3IgZGV2ZWxvcG1lbnQuCiAgIFlvdSBuZWVkIHRvIGlu
+c3RhbGwgYSBsb25nIGxpc3Qgb2YgdG9vbHMgZm9yIGJ1aWxkaW5nLiAgVGhpcyBs
+aXN0CiAgIHN0aWxsIG5lZWRzIHRvIGJlIGNvbXBpbGVkLiAgSG93ZXZlciwgdGhl
+IGJ1aWxkIHByb2Nlc3Mgd2lsbCBzdG9wCiAgIGlmIGEgdG9vbCBpcyBtaXNzaW5n
+LiAgR05VIG1ha2UgaXMgcmVxdWlyZWQgKG9uIG5vbiBHTlUgc3lzdGVtcwogICBv
+ZnRlbiBpbnN0YWxsZWQgYXMgImdtYWtlIikuICBUaGUgaW5zdGFsbGVyIHJlcXVp
+cmVzIGEgY291cGxlIG9mCiAgIGV4dHJhIHNvZnR3YXJlIHRvIGJlIGF2YWlsYWJs
+ZSBlaXRoZXIgYXMgdGFyYmFsbHMgb3IgYXMgbG9jYWwgZ2l0CiAgIHJlcG9zaXRv
+cmllcy4gIEluIGNhc2UgdGhpcyBmaWxlIGhlcmUgaXMgcGFydCBvZiBhIGdudXBn
+LXczMi0yLioueHoKICAgY29tcGxldGUgdGFyYmFsbCBhcyBkaXN0cmlidXRlZCBm
+cm9tIHRoZSBzYW1lIHBsYWNlIGFzIGEgYmluYXJ5CiAgIGluc3RhbGxlciwgYWxs
+IHN1Y2ggdGFyYmFsbHMgYXJlIGFscmVhZHkgaW5jbHVkZWQuCgogICBDZCB0byB0
+aGUgR251UEcgc291cmNlIGRpcmVjdG9yeSBhbmQgdXNlIG9uZSBvZiBvbmUgb2Yg
+dGhlc2UKICAgY29tbWFuZDoKCiAgIC0gSWYgc291cmNlcyBhcmUgaW5jbHVkZWQg
+KGdudXBnLXczMi0qLnRhci54eikKCiAgICAgbWFrZSAtZiBidWlsZC1hdXgvc3Bl
+ZWRvLm1rIFdIQVQ9dGhpcyBpbnN0YWxsZXIKCiAgIC0gVG8gYnVpbGQgZnJvbSB0
+YXJiYWxscwoKICAgICBtYWtlIC1mIGJ1aWxkLWF1eC9zcGVlZG8ubWsgV0hBVD1y
+ZWxlYXNlIFRBUkJBTExTPVRBUkRJUiBpbnN0YWxsZXIKCiAgIC0gVG8gYnVpbGQg
+ZnJvbSBsb2NhbCBHSVQgcmVwb3MKCiAgICAgbWFrZSAtZiBidWlsZC1hdXgvc3Bl
+ZWRvLm1rIFdIQVQ9Z2l0IFRBUkJBTExTPVRBUkRJUiBpbnN0YWxsZXIKCiAgIE5v
+dGUgdGhhdCBhbHNvIHlvdSBuZWVkIHRvIHN1cHBseSB0YXJiYWxscyB3aXRoIHN1
+cHBvcnRpbmcKICAgbGlicmFyaWVzIGV2ZW4gaWYgeW91IGJ1aWxkIGZyb20gZ2l0
+LiAgVGhlIG1ha2VmaWxlIGV4cGVjdHMgb25seQogICB0aGUgY29yZSBHbnVQRyBz
+b2Z0d2FyZSB0byBiZSBhdmFpbGFibGUgYXMgbG9jYWwgR0lUIHJlcG9zaXRvcmll
+cy4KICAgc3BlZWRvLm1rIGhhcyB0aGUgdmVyc2lvbnMgb2YgdGhlIHRhcmJhbGxz
+IGFuZCB0aGUgYnJhbmNoIG5hbWVzIG9mCiAgIHRoZSBnaXQgcmVwb3NpdG9yaWVz
+LiAgSW4gY2FzZSBvZiBwcm9ibGVtcywgZG9uJ3QgaGVzaXRhdGUgdG8gYXNrCiAg
+IG9uIHRoZSBnbnVwZy1kZXZlbCBtYWlsaW5nIGZvciBoZWxwLgoKKiBEZWJ1ZyBo
+aW50cwoKICBTZWUgdGhlIG1hbnVhbCBmb3Igc29tZSBoaW50cy4KCiogU3RhbmRh
+cmRzCioqIFJGQ3MKCjE0MjMgIFByaXZhY3kgRW5oYW5jZW1lbnQgZm9yIEludGVy
+bmV0IEVsZWN0cm9uaWMgTWFpbDoKICAgICAgUGFydCBJSUk6IEFsZ29yaXRobXMs
+IE1vZGVzLCBhbmQgSWRlbnRpZmllcnMuCgoxNDg5ICBSZWdpc3RyYXRpb24gb2Yg
+YSBDeXJpbGxpYyBDaGFyYWN0ZXIgU2V0LgoKMTc1MCAgUmFuZG9tbmVzcyBSZWNv
+bW1lbmRhdGlvbnMgZm9yIFNlY3VyaXR5LgoKMTk5MSAgUEdQIE1lc3NhZ2UgRXhj
+aGFuZ2UgRm9ybWF0cyAob2Jzb2xldGUpCgoyMTQ0ICBUaGUgQ0FTVC0xMjggRW5j
+cnlwdGlvbiBBbGdvcml0aG0uCgoyMjc5ICBVVEYtOCwgYSB0cmFuc2Zvcm1hdGlv
+biBmb3JtYXQgb2YgSVNPIDEwNjQ2LgoKMjQ0MCAgT3BlblBHUCAob2Jzb2xldGUp
+LgoKMzE1NiAgTUlNRSBTZWN1cml0eSB3aXRoIFByZXR0eSBHb29kIFByaXZhY3kg
+KFBHUCkuCgo0ODgwICBDdXJyZW50IE9wZW5QR1Agc3BlY2lmaWNhdGlvbi4KCjYz
+MzcgIEVsbGlwdGljIEN1cnZlIENyeXB0b2dyYXBoeSAoRUNDKSBpbiBPcGVuUEdQ
+CgoqIFZhcmlvdXMgaW5mb3JtYXRpb24KCioqIERpcmVjdG9yeSBMYXlvdXQKCiAg
+LSAuLwkgICAgICA6OiBSZWFkbWUsIGNvbmZpZ3VyZQogIC0gLi9hZ2VudCAgIDo6
+IEdwZy1hZ2VudCBhbmQgcmVsYXRlZCB0b29scwogIC0gLi9kb2MgICAgIDo6IERv
+Y3VtZW50YXRpb24KICAtIC4vZzEwICAgICA6OiBHcGcgcHJvZ3JhbSBoZXJlIGNh
+bGxlZCBncGcyCiAgLSAuL3NtICAgICAgOjogR3Bnc20gcHJvZ3JhbQogIC0gLi9q
+bmxpYiAgIDo6IE5vdCB1c2VkIChmb3JtZXJseSB1c2VkIHV0aWxpdHkgZnVuY3Rp
+b25zKQogIC0gLi9jb21tb24gIDo6IFV0aWxpdHkgZnVuY3Rpb25zCiAgLSAuL2ti
+eCAgICAgOjogS2V5Ym94IGxpYnJhcnkKICAtIC4vc2NkICAgICA6OiBTbWFydGNh
+cmQgZGFlbW9uCiAgLSAuL3NjcmlwdHMgOjogU2NyaXB0cyBuZWVkZWQgYnkgY29u
+ZmlndXJlIGFuZCBvdGhlcnMKICAtIC4vZGlybW5nciA6OiBUaGUgZGlyZWN0b3J5
+IG1hbmFnZXIKCioqIERldGFpbGVkIFJvYWRtYXAKCiAgVGhpcyBsaXN0IG9mIGZp
+bGVzIGlzIG5vdCB1cCB0byBkYXRlIQoKICAtIGcxMC9ncGcuYyA6OiBNYWluIG1v
+ZHVsZSB3aXRoIG9wdGlvbiBwYXJzaW5nIGFuZCBhbGwgdGhlIHN0dWZmIHlvdQog
+ICAgICAgICAgICAgICAgIGhhdmUgdG8gZG8gb24gc3RhcnR1cC4gIEFsc28gaGFz
+IHRoZSBleGl0IGhhbmRsZXIgYW5kCiAgICAgICAgICAgICAgICAgc29tZSBoZWxw
+ZXIgZnVuY3Rpb25zLgoKICAtIGcxMC9wYXJzZS1wYWNrZXQuYyA6OgogIC0gZzEw
+L2J1aWxkLXBhY2tldC5jIDo6CiAgLSBnMTAvZnJlZS1wYWNrZXQuYyA6OiBQYXJz
+aW5nIGFuZCBjcmVhdGluZyBvZiBPcGVuUEdQIG1lc3NhZ2UgcGFja2V0cy4KCiAg
+LSBnMTAvZ2V0a2V5LmMgICA6OiBLZXkgc2VsZWN0aW9uIGNvZGUKICAtIGcxMC9w
+a2NsaXN0LmMgIDo6IEJ1aWxkIGEgbGlzdCBvZiBwdWJsaWMga2V5cwogIC0gZzEw
+L3NrY2xpc3QuYyAgOjogQnVpbGQgYSBsaXN0IG9mIHNlY3JldCBrZXlzCiAgLSBn
+MTAva2V5cmluZy5jICA6OiBLZXlyaW5nIGFjY2VzcyBmdW5jdGlvbnMKICAtIGcx
+MC9rZXlkYi5oICAgIDo6CgogIC0gZzEwL2tleWlkLmMJICA6OiBIZWxwZXIgZnVu
+Y3Rpb25zIHRvIGdldCB0aGUga2V5aWQsIGZpbmdlcnByaW50IGV0Yy4KCiAgLSBn
+MTAvdHJ1c3RkYi5jIDo6IFdlYi1vZi1UcnVzdCBjb21wdXRhdGlvbnMKICAtIGcx
+MC90cnVzdGRiLmggOjoKICAtIGcxMC90ZGJkdW1wLmMgOjogRXhwb3J0L2ltcG9y
+dC9saXN0IHRoZSB0cnVzdGRiLmdwZwogIC0gZzEwL3RkYmlvLmMgICA6OiBJL08g
+aGFuZGxpbmcgZm9yIHRoZSB0cnVzdGRiLmdwZwogIC0gZzEwL3RkYmlvLmggICA6
+OgoKICAtIGcxMC9jb21wcmVzcy5jIDo6IEZpbHRlciB0byBoYW5kbGUgY29tcHJl
+c3Npb24KICAtIGcxMC9maWx0ZXIuaCAgIDo6IERlY2xhcmF0aW9ucyBmb3IgYWxs
+IGZpbHRlciBmdW5jdGlvbnMKICAtIGcxMC9kZWxrZXkuYyAgIDo6IERlbGV0ZSBh
+IGtleQogIC0gZzEwL2tibm9kZS5jICAgOjogSGVscGVyIGZvciB0aGUga2Jub2Rl
+X3QgbGlua2VkIGxpc3QKICAtIGcxMC9tYWluLmggICAgIDo6IFByb3RvdHlwZXMg
+YW5kIHNvbWUgY29uc3RhbnRzCiAgLSBnMTAvbWFpbnByb2MuYyA6OiBNZXNzYWdl
+IHByb2Nlc3NpbmcKICAtIGcxMC9hcm1vci5jICAgIDo6IEFzY2lpIGFybW9yIGZp
+bHRlcgogIC0gZzEwL21kZmlsdGVyLmMgOjogRmlsdGVyIHRvIGNhbGN1bGF0ZSBo
+YXNocwogIC0gZzEwL3RleHRmaWx0ZXIuYyA6OiBGaWx0ZXIgdG8gaGFuZGxlIENS
+L0xGIGFuZCB0cmFpbGluZyB3aGl0ZSBzcGFjZQogIC0gZzEwL2NpcGhlci5jICAg
+OjogRW4tL0RlY3J5cHRpb24gZmlsdGVyCiAgLSBnMTAvbWlzYy5jICAgICA6OiBV
+dGxpdHkgZnVuY3Rpb25zCiAgLSBnMTAvb3B0aW9ucy5oICA6OiBTdHJ1Y3R1cmUg
+d2l0aCBhbGwgdGhlIGNvbW1hbmQgbGluZSBvcHRpb25zCiAgICAgICAgICAgICAg
+ICAgICAgICBhbmQgcmVsYXRlZCBjb25zdGFudHMKICAtIGcxMC9vcGVuZmlsZS5j
+IDo6IENyZWF0ZS9PcGVuIEZpbGVzCiAgLSBnMTAva2V5c2VydmVyLmggOjogS2V5
+c2VydmVyIGFjY2VzcyBkaXNwYXRjaGVyLgogIC0gZzEwL3BhY2tldC5oICAgOjog
+RGVmaW50aW9uIG9mIE9wZW5QR1Agc3RydWN0dXJlcy4KICAtIGcxMC9wYXNzcGhy
+YXNlLmMgOjogUGFzc3BocmFzZSBoYW5kbGluZyBjb2RlCgogIC0gZzEwL3B1Ymtl
+eS1lbmMuYyA6OiBQcm9jZXNzIGEgcHVibGljIGtleSBlbmNvZGVkIHBhY2tldC4K
+ICAtIGcxMC9zZWNrZXktY2VydC5jIDo6IE5vdCBhbnltb3JlIHVzZWQKICAtIGcx
+MC9zZXNrZXkuYyAgICAgOjogTWFrZSBzZXNzc2lvbiBrZXlzIGV0Yy4KICAtIGcx
+MC9pbXBvcnQuYyAgICAgOjogSW1wb3J0IGtleXMgaW50byBvdXIga2V5IHN0b3Jh
+Z2UuCiAgLSBnMTAvZXhwb3J0LmMgICAgIDo6IEV4cG9ydCBrZXlzIHRvIHRoZSBP
+cGVuUEdQIGZvcm1hdC4KICAtIGcxMC9zaWduLmMgICAgICAgOjogQ3JlYXRlIHNp
+Z25hdHVyZSBhbmQgb3B0aW9uYWxseSBlbmNyeXB0LgogIC0gZzEwL3BsYWludGV4
+dC5jICA6OiBQcm9jZXNzIHBsYWludGV4dCBwYWNrZXRzLgogIC0gZzEwL2RlY3J5
+cHQtZGF0YS5jIDo6IERlY3J5cHQgYW4gZW5jcnlwdGVkIGRhdGEgcGFja2V0CiAg
+LSBnMTAvZW5jcnlwdC5jICAgIDo6IE1haW4gZW5jcnlwdGlvbiBkcml2ZXIKICAt
+IGcxMC9yZXZva2UuYyAgICAgOjogQ3JlYXRlIHJlY292YXRpb24gY2VydGlmaWNh
+dGVzLgogIC0gZzEwL2tleWxpc3QuYyAgICA6OiBQcmludCBpbmZvcm1hdGlvbiBh
+Ym91dCBPcGVuUEdQIGtleXMKICAtIGcxMC9zaWctY2hlY2suYyAgOjogQ2hlY2sg
+YSBzaWduYXR1cmUKICAtIGcxMC9oZWxwdGV4dC5jICAgOjogU2hvdyBvbmxpbmUg
+aGVscCB0ZXh0cwogIC0gZzEwL3ZlcmlmeS5jICAgICA6OiBWZXJpZnkgc2lnbmVk
+IGRhdGEuCiAgLSBnMTAvZGVjcnlwdC5jICAgIDo6IERlY3J5cHQgYW5kIHZlcmlm
+eSBkYXRhLgogIC0gZzEwL2tleWVkaXQuYyAgICA6OiBFZGl0IHByb3BlcnRpZXMg
+b2YgYSBrZXkuCiAgLSBnMTAvZGVhcm1vci5jICAgIDo6IEFybW9yIHV0aWxpdHku
+CiAgLSBnMTAva2V5Z2VuLmMgICAgIDo6IEdlbmVyYXRlIGEga2V5IHBhaXIKCioq
+IE1lbW9yeSBhbGxvY2F0aW9uCgpVc2Ugb25seSB0aGUgZnVuY3Rpb25zOgoKIC0g
+eG1hbGxvYwogLSB4bWFsbG9jX3NlY3VyZQogLSB4dHJ5bWFsbG9jCiAtIHh0cnlt
+YWxsb2Nfc2VjdXJlCiAtIHhjYWxsb2MKIC0geGNhbGxvY19zZWN1cmUKIC0geHRy
+eWNhbGxvYwogLSB4dHJ5Y2FsbG9jX3NlY3VyZQogLSB4cmVhbGxvYwogLSB4dHJ5
+cmVhbGxvYwogLSB4c3RyZHVwCiAtIHh0cnlzdHJkdXAKIC0geGZyZWUKCgpUaGUg
+KnNlY3VyZSB2ZXJzaW9ucyBhbGxvY2F0ZSBtZW1vcnkgaW4gdGhlIHNlY3VyZSBt
+ZW1vcnkuICBUaGF0IGlzLApzd2FwcGluZyBvdXQgb2YgdGhpcyBtZW1vcnkgaXMg
+YXZvaWRlZCBhbmQgaXMgZ2V0cyBvdmVyd3JpdHRlbiBvbgpmcmVlLiAgVXNlIHRo
+aXMgZm9yIHBhc3NwaHJhc2VzLCBzZXNzaW9uIGtleXMgYW5kIG90aGVyIHNlbnNp
+dGl2ZQptYXRlcmlhbC4gIFRoaXMgbWVtb3J5IHNldCBhc2lkZSBmb3Igc2VjdXJl
+IG1lbW9yeSBpcyBsaW5pdGVkIHRvIGEgZmV3CmsuICBJbiBnZW5lcmFsIHRoZSBm
+dW5jdGlvbiBkb24ndCBwcmludCBhIG1lbWVvcnkgbWVzc2FnZSBhbmQKdGVybWlu
+YXRlIHRoZSBwcm9jZXNzIGlmIHRoZXJlIGlzIG5vdCBlbm91Z2ggbWVtb3J5IGF2
+YWlsYWJsZS4gIFRoZQoidHJ5IiB2ZXJzaW9ucyBvZiB0aGUgZnVuY3Rpb25zIHJl
+dHVybiBOVUxMIGluc3RlYWQuCgoqKiBMb2dnaW5nCgogVE9ETwoKKiogT3B0aW9u
+IHBhcnNpbmcKCkdudVBHIGRvZXMgbm90IHVzZSBnZXRvcHQgb3IgR05VIGdldG9w
+dCBidXQgZnVuY3Rpb25zIG9mIGl0J3Mgb3duLgpTZWUgdXRpbC9hcmdwYXJzZS5j
+IGZvciBkZXRhaWxzLiAgVGhlIGFkdmFudGFnZSBvZiB0aGVzZSBmdW5jdGlvbnMg
+aXMKdGhhdCBpdCBpcyBtb3JlIGVhc3kgdG8gZGlzcGxheSBhbmQgbWFpbnRhaW4g
+dGhlIGhlbHAgdGV4dHMgZm9yIHRoZQpvcHRpb25zLiAgVGhlIHNhbWUgb3B0aW9u
+IHRhYmxlIGlzIGFsc28gdXNlZCB0byBwYXJzZSByZXNvdXJjZSBmaWxlcy4KCioq
+IFdoYXQgaXMgYW4gSU9CVUYKClRoaXMgaXMgdGhlIGRhdGEgc3RydWN0dXJlIHVz
+ZWQgZm9yIG1vc3QgSS9PIG9mIGdudXBnLiBJdCBpcyBzaW1pbGFyCnRvIFN5c3Rl
+bcKgViBTdHJlYW1zIGJ1dCBtdWNoIHNpbXBsZXIuICBCZWNhdXNlIE9wZW5QR1Ag
+bWVzc2FnZXMgYXJlCm5lc3RlZCBpbiBkaWZmZXJlbnQgd2F5czsgdGhlIHVzZSBv
+ZiBzdWNoIGEgc3lzdGVtIGhhcyBiaWcgYWR2YW50YWdlcy4KSGVyZSBpcyBhbiBl
+eGFtcGxlLCBob3cgaXQgd29ya3M6IElmIHRoZSBwYXJzZXIgc2VlcyBhIHBhY2tl
+dCBoZWFkZXIKd2l0aCBhIHBhcnRpYWwgbGVuZ3RoLCBpdCBwdXNoZXMgdGhlIGJs
+b2NrX2ZpbHRlciBvbnRvIHRoZSBJT0JVRiB0bwpoYW5kbGUgdGhlc2UgcGFydGlh
+bCBsZW5ndGggcGFja2V0czogZnJvbSBub3cgb24geW91IGRvbid0IGhhdmUgdG8K
+d29ycnkgYWJvdXQgdGhpcy4gIFdoZW4gaXQgc2VlcyBhIGNvbXByZXNzZWQgcGFj
+a2V0IGl0IHB1c2hlcyB0aGUKdW5jb21wcmVzcyBmaWx0ZXIgYW5kIHRoZSBuZXh0
+IHJlYWQgYnl0ZSBpcyBvbmUgd2hpY2ggaGFzIGFscmVhZHkgYmVlbgp1bmNvbXBy
+ZXNzZWQgYnkgdGhpcyBmaWx0ZXIuIFNhbWUgZ29lcyBmb3IgZW5jaXBoZXJlZCBw
+YWNrZXQsCnBsYWludGV4dCBwYWNrZXRzIGFuZCBzbyBvbi4gIFRoZSBmaWxlIGcx
+MC9lbmNvZGUuYyBtaWdodCBiZSBhIGdvb2QKc3RhcnRpbmcgcG9pbnQgdG8gc2Vl
+IGhvdyBpdCBpcyB1c2VkIC0gYWN0dWFsbHkgdGhpcyBpcyB0aGUgb3RoZXIgd2F5
+Ogpjb25zdHJ1Y3RpbmcgbWVzc2FnZXMgdXNpbmcgcHVzaGVkIGZpbHRlcnMgYnV0
+IGl0IG1heSBiZSBlYXNpZXIgdG8KdW5kZXJzdGFuZC4KCgojIGRvYy9ERVRBSUxT
+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
+LSotIG9yZyAtKi0KIytUSVRMRTogR251UEcgRGV0YWlscwojIEdsb2JhbGx5IGRp
+c2FibGUgc3VwZXJzY3JpcHRzIGFuZCBzdWJzY3JpcHRzOgojK09QVElPTlM6IF46
+e30KIwoKIyBOb3RlOiBUaGlzIGZpbGUgdXNlcyBvcmctbW9kZTsgaXQgc2hvdWxk
+IGJlIGVhc3kgdG8gcmVhZCBhcyBwbGFpbgojIHRleHQgYnV0IGJlIGF3YXJlIG9m
+IHNvbWUgbWFya3VwIHBlY3VsaWFyaXRpZXM6IFZlcmJhdGltIGNvZGUgaXMKIyBl
+bmNsb3NlZCBpbiAjK2JlZ2luLWV4YW1wbGUsICMrZW5kLWV4YW1wbGUgYmxvY2tz
+IG9yIG1hcmtlZCBieSBhCiMgY29sb24gYXMgdGhlIGZpcnN0IG5vbi13aGl0ZS1z
+cGFjZSBjaGFyYWN0ZXIsIHdvcmRzIGJyYWNrZXRlZCB3aXRoCiMgZXF1YWwgc2ln
+bnMgaW5kaWNhdGUgYSBtb25vc3BhY2UgZm9udCwgYW5kIHRoZSB1c3VhbCAvaXRh
+bGljcy8sCiMgKmJvbGQqLCBhbmQgX3VuZGVybGluZV8gY29udmVudGlvbnMgYXJl
+IHJlY29nbml6ZWQuCgpUaGlzIGlzIHRoZSBERVRBSUxTIGZpbGUgZm9yIEdudVBH
+IHdoaWNoIHNwZWNpZmllcyBzb21lIGludGVybmFscyBhbmQKcGFydHMgb2YgdGhl
+IGV4dGVybmFsIEFQSSBmb3IgR1BHIGFuZCBHUEdTTS4KCiogRm9ybWF0IG9mIHRo
+ZSBjb2xvbiBsaXN0aW5ncwogIFRoZSBmb3JtYXQgaXMgYSBiYXNlZCBvbiBjb2xv
+biBzZXBhcmF0ZWQgcmVjb3JkLCBlYWNoIHJlY29kcyBzdGFydHMKICB3aXRoIGEg
+dGFnIHN0cmluZyBhbmQgZXh0ZW5kcyB0byB0aGUgZW5kIG9mIHRoZSBsaW5lLiAg
+SGVyZSBpcyBhbgogIGV4YW1wbGU6CiMrYmVnaW5fZXhhbXBsZQokIGdwZyAtLXdp
+dGgtY29sb25zIC0tbGlzdC1rZXlzIFwKICAgICAgLS13aXRoLWZpbmdlcnByaW50
+IC0td2l0aC1maW5nZXJwcmludCB3a0BnbnVwZy5vcmcKcHViOmY6MTAyNDoxNzo2
+QzdFRTFCODYyMUNDMDEzOjg5OTgxNzcxNToxMDU1ODk4MjM1OjptOjo6c2NFU0M6
+CmZwcjo6Ojo6Ojo6OkVDQUY3NTkwRUIzNDQzQjVDN0NGM0FDQjZDN0VFMUI4NjIx
+Q0MwMTM6CnVpZDpmOjo6Ojo6OjpXZXJuZXIgS29jaCA8d2tAZzEwY29kZS5jb20+
+Ogp1aWQ6Zjo6Ojo6Ojo6V2VybmVyIEtvY2ggPHdrQGdudXBnLm9yZz46CnN1Yjpm
+OjE1MzY6MTY6MDZBRDIyMkNBREY2QTZFMTo5MTk1Mzc0MTY6MTAzNjE3NzQxNjo6
+Ojo6ZToKZnByOjo6Ojo6Ojo6Q0Y4QkNDNEIxOERFMDhGQ0Q4QTE2MTU5MDZBRDIy
+MkNBREY2QTZFMToKc3ViOnI6MTUzNjoyMDo1Q0UwODZCNUI1QTE4RkY0Ojg5OTgx
+Nzc4ODoxMDI1OTYxNzg4Ojo6Ojplc2M6CmZwcjo6Ojo6Ojo6OkFCMDU5MzU5QTNC
+ODFGNDEwRkNGRjk3RjVDRTA4NkI1QjVBMThGRjQ6CiMrZW5kX2V4YW1wbGUKClRo
+ZSBkb3VibGUgPS0td2l0aC1maW5nZXJwcmludD0gcHJpbnRzIHRoZSBmaW5nZXJw
+cmludCBmb3IgdGhlIHN1YmtleXMKdG9vLiAgT2xkIHZlcnNpb25zIG9mIGdwZyB1
+c2VkIGEgc2xpZ2h0bHkgZGlmZmVyZW50IGZvcm1hdCBhbmQgcmVxdWlyZWQKdGhl
+IHVzZSBvZiB0aGUgb3B0aW9uID0tLWZpeGVkLWxpc3QtbW9kZT0gdG8gY29uZm9y
+bSB0byB0aGUgZm9ybWF0CmRlc2NyaWJlZCBoZXJlLgoKKiogRGVzY3JpcHRpb24g
+b2YgdGhlIGZpZWxkcwoqKiogRmllbGQgMSAtIFR5cGUgb2YgcmVjb3JkCgogICAg
+LSBwdWIgOjogUHVibGljIGtleQogICAgLSBjcnQgOjogWC41MDkgY2VydGlmaWNh
+dGUKICAgIC0gY3JzIDo6IFguNTA5IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtl
+eSBhdmFpbGFibGUKICAgIC0gc3ViIDo6IFN1YmtleSAoc2Vjb25kYXJ5IGtleSkK
+ICAgIC0gc2VjIDo6IFNlY3JldCBrZXkKICAgIC0gc3NiIDo6IFNlY3JldCBzdWJr
+ZXkgKHNlY29uZGFyeSBrZXkpCiAgICAtIHVpZCA6OiBVc2VyIGlkIChvbmx5IGZp
+ZWxkIDEwIGlzIHVzZWQpLgogICAgLSB1YXQgOjogVXNlciBhdHRyaWJ1dGUgKHNh
+bWUgYXMgdXNlciBpZCBleGNlcHQgZm9yIGZpZWxkIDEwKS4KICAgIC0gc2lnIDo6
+IFNpZ25hdHVyZQogICAgLSByZXYgOjogUmV2b2NhdGlvbiBzaWduYXR1cmUKICAg
+IC0gZnByIDo6IEZpbmdlcnByaW50IChmaW5nZXJwcmludCBpcyBpbiBmaWVsZCAx
+MCkKICAgIC0gcGtkIDo6IFB1YmxpYyBrZXkgZGF0YSBbKl0KICAgIC0gZ3JwIDo6
+IEtleWdyaXAKICAgIC0gcnZrIDo6IFJldm9jYXRpb24ga2V5CiAgICAtIHRydSA6
+OiBUcnVzdCBkYXRhYmFzZSBpbmZvcm1hdGlvbiBbKl0KICAgIC0gc3BrIDo6IFNp
+Z25hdHVyZSBzdWJwYWNrZXQgWypdCiAgICAtIGNmZyA6OiBDb25maWd1cmF0aW9u
+IGRhdGEgWypdCgogICAgUmVjb3JkcyBtYXJrZWQgd2l0aCBhbiBhc3RlcmlzayBh
+cmUgZGVzY3JpYmVkIGF0IFtbKlNwZWNpYWwlMjBmaWVsZCUyMGZvcm1hdHNdWypT
+cGVjaWFsIGZpZWxkc11dLgoKKioqIEZpZWxkIDIgLSBWYWxpZGl0eQoKICAgIFRo
+aXMgaXMgYSBsZXR0ZXIgZGVzY3JpYmluZyB0aGUgY29tcHV0ZWQgdmFsaWRpdHkg
+b2YgYSBrZXkuCiAgICBDdXJyZW50bHkgdGhpcyBpcyBhIHNpbmdsZSBsZXR0ZXIs
+IGJ1dCBiZSBwcmVwYXJlZCB0aGF0IGFkZGl0aW9uYWwKICAgIGluZm9ybWF0aW9u
+IG1heSBmb2xsb3cgaW4gc29tZSBmdXR1cmUgdmVyc2lvbnMuIE5vdGUgdGhhdCBH
+bnVQRyA8CiAgICAyLjEgZG9lcyBub3Qgc2V0IHRoaXMgZmllbGQgZm9yIHNlY3Jl
+dCBrZXkgbGlzdGluZ3MuCgogICAgLSBvIDo6IFVua25vd24gKHRoaXMga2V5IGlz
+IG5ldyB0byB0aGUgc3lzdGVtKQogICAgLSBpIDo6IFRoZSBrZXkgaXMgaW52YWxp
+ZCAoZS5nLiBkdWUgdG8gYSBtaXNzaW5nIHNlbGYtc2lnbmF0dXJlKQogICAgLSBk
+IDo6IFRoZSBrZXkgaGFzIGJlZW4gZGlzYWJsZWQKCSAgIChkZXByZWNhdGVkIC0g
+dXNlIHRoZSAnRCcgaW4gZmllbGQgMTIgaW5zdGVhZCkKICAgIC0gciA6OiBUaGUg
+a2V5IGhhcyBiZWVuIHJldm9rZWQKICAgIC0gZSA6OiBUaGUga2V5IGhhcyBleHBp
+cmVkCiAgICAtIC0gOjogVW5rbm93biB2YWxpZGl0eSAoaS5lLiBubyB2YWx1ZSBh
+c3NpZ25lZCkKICAgIC0gcSA6OiBVbmRlZmluZWQgdmFsaWRpdHkuICAnLScgYW5k
+ICdxJyBtYXkgc2FmZWx5IGJlIHRyZWF0ZWQgYXMKICAgICAgICAgICB0aGUgc2Ft
+ZSB2YWx1ZSBmb3IgbW9zdCBwdXJwb3NlcwogICAgLSBuIDo6IFRoZSBrZXkgaXMg
+bm90IHZhbGlkCiAgICAtIG0gOjogVGhlIGtleSBpcyBtYXJnaW5hbCB2YWxpZC4K
+ICAgIC0gZiA6OiBUaGUga2V5IGlzIGZ1bGx5IHZhbGlkCiAgICAtIHUgOjogVGhl
+IGtleSBpcyB1bHRpbWF0ZWx5IHZhbGlkLiAgVGhpcyBvZnRlbiBtZWFucyB0aGF0
+IHRoZQogICAgICAgICAgIHNlY3JldCBrZXkgaXMgYXZhaWxhYmxlLCBidXQgYW55
+IGtleSBtYXkgYmUgbWFya2VkIGFzCiAgICAgICAgICAgdWx0aW1hdGVseSB2YWxp
+ZC4KICAgIC0gdyA6OiBUaGUga2V5IGhhcyBhIHdlbGwga25vd24gcHJpdmF0ZSBw
+YXJ0LgogICAgLSBzIDo6IFRoZSBrZXkgaGFzIHNwZWNpYWwgdmFsaWRpdHkuICBU
+aGlzIG1lYW5zIHRoYXQgaXQgbWlnaHQgYmUKICAgICAgICAgICBzZWxmLXNpZ25l
+ZCBhbmQgZXhwZWN0ZWQgdG8gYmUgdXNlZCBpbiB0aGUgU1RFRUQgc3l0ZW0uCgog
+ICAgSWYgdGhlIHZhbGlkaXR5IGluZm9ybWF0aW9uIGlzIGdpdmVuIGZvciBhIFVJ
+RCBvciBVQVQgcmVjb3JkLCBpdAogICAgZGVzY3JpYmVzIHRoZSB2YWxpZGl0eSBj
+YWxjdWxhdGVkIGJhc2VkIG9uIHRoaXMgdXNlciBJRC4gIElmIGdpdmVuCiAgICBm
+b3IgYSBrZXkgcmVjb3JkIGl0IGRlc2NyaWJlcyB0aGUgdmFsaWRpdHkgdGFrZW4g
+ZnJvbSB0aGUgYmVzdAogICAgcmF0ZWQgdXNlciBJRC4KCiAgICBGb3IgWC41MDkg
+Y2VydGlmaWNhdGVzIGEgJ3UnIGlzIHVzZWQgZm9yIGEgdHJ1c3RlZCByb290CiAg
+ICBjZXJ0aWZpY2F0ZSAoaS5lLiBmb3IgdGhlIHRydXN0IGFuY2hvcikgYW5kIGFu
+ICdmJyBmb3IgYWxsIG90aGVyCiAgICB2YWxpZCBjZXJ0aWZpY2F0ZXMuCgoqKiog
+RmllbGQgMyAtIEtleSBsZW5ndGgKCiAgICBUaGUgbGVuZ3RoIG9mIGtleSBpbiBi
+aXRzLgoKKioqIEZpZWxkIDQgLSBQdWJsaWMga2V5IGFsZ29yaXRobQoKICAgIFRo
+ZSB2YWx1ZXMgaGVyZSBhcmUgdGhvc2UgZnJvbSB0aGUgT3BlblBHUCBzcGVjcyBv
+ciBpZiB0aGV5IGFyZQogICAgZ3JlYXRoZXIgdGhhbiAyNTUgdGhlIGFsZ29yaXRo
+bSBpZHMgYXMgdXNlZCBieSBMaWJnY3J5cHQuCgoqKiogRmllbGQgNSAtIEtleUlE
+CgogICAgVGhpcyBpcyB0aGUgNjQgYml0IGtleWlkIGFzIHNwZWNpZmllZCBieSBP
+cGVuUEdQIGFuZCB0aGUgbGFzdCA2NAogICAgYml0IG9mIHRoZSBTSEEtMSBmaW5n
+ZXJwcmludCBvZiBhbiBYLjUwOSBjZXJ0aWZjaWF0ZS4KCioqKiBGaWVsZCA2IC0g
+Q3JlYXRpb24gZGF0ZQoKICAgIFRoZSBjcmVhdGlvbiBkYXRlIG9mIHRoZSBrZXkg
+aXMgZ2l2ZW4gaW4gVVRDLiAgRm9yIFVJRCBhbmQgVUFUCiAgICByZWNvcmRzLCB0
+aGlzIGlzIHVzZWQgZm9yIHRoZSBzZWxmLXNpZ25hdHVyZSBkYXRlLiAgTm90ZSB0
+aGF0IHRoZQogICAgZGF0ZSBpcyB1c2FsbHkgcHJpbnRlZCBpbiBzZWNvbmRzIHNp
+bmNlIGVwb2NoLCBob3dldmVyLCB3ZSBhcmUKICAgIG1pZ3JhdGluZyB0byBhbiBJ
+U08gODYwMSBmb3JtYXQgKGUuZy4gIjE5NjYwMjA1VDA5MTUwMCIpLiAgVGhpcyBp
+cwogICAgY3VycmVudGx5IG9ubHkgcmVsZXZhbnQgZm9yIFguNTA5LiAgQSBzaW1w
+bGUgd2F5IHRvIGRldGVjdCB0aGUgbmV3CiAgICBmb3JtYXQgaXMgdG8gc2NhbiBm
+b3IgdGhlICdUJy4gIE5vdGUgdGhhdCBvbGQgdmVyc2lvbnMgb2YgZ3BnCiAgICB3
+aXRob3V0IHVzaW5nIHRoZSA9LS1maXhlZC1saXN0LW1vZGU9IG9wdGlvbiB1c2Vk
+IGEgInl5eXktbW0tdHQiCiAgICBmb3JtYXQuCgoqKiogRmllbGQgNyAtIEV4cGly
+YXRpb24gZGF0ZQoKICAgIEtleSBvciBVSUQvVUFUIGV4cGlyYXRpb24gZGF0ZSBv
+ciBlbXB0eSBpZiBpdCBkb2VzIG5vdCBleHBpcmUuCgoqKiogRmllbGQgOCAtIENl
+cnRpZmljYXRlIFMvTiwgVUlEIGhhc2gsIHRydXN0IHNpZ25hdHVyZSBpbmZvCgog
+ICAgVXNlZCBmb3Igc2VyaWFsIG51bWJlciBpbiBjcnQgcmVjb3Jkcy4gIEZvciBV
+SUQgYW5kIFVBVCByZWNvcmRzLAogICAgdGhpcyBpcyBhIGhhc2ggb2YgdGhlIHVz
+ZXIgSUQgY29udGVudHMgdXNlZCB0byByZXByZXNlbnQgdGhhdAogICAgZXhhY3Qg
+dXNlciBJRC4gIEZvciB0cnVzdCBzaWduYXR1cmVzLCB0aGlzIGlzIHRoZSB0cnVz
+dCBkZXB0aAogICAgc2VwZXJhdGVkIGJ5IHRoZSB0cnVzdCB2YWx1ZSBieSBhIHNw
+YWNlLgoKKioqIEZpZWxkIDkgLSAgT3duZXJ0cnVzdAoKICAgIFRoaXMgaXMgb25s
+eSB1c2VkIG9uIHByaW1hcnkga2V5cy4gIFRoaXMgaXMgYSBzaW5nbGUgbGV0dGVy
+LCBidXQKICAgIGJlIHByZXBhcmVkIHRoYXQgYWRkaXRpb25hbCBpbmZvcm1hdGlv
+biBtYXkgZm9sbG93IGluIGZ1dHVyZQogICAgdmVyc2lvbnMuICBGb3IgdHJ1c3Qg
+c2lnbmF0dXJlcyB3aXRoIGEgcmVndWxhciBleHByZXNzaW9uLCB0aGlzIGlzCiAg
+ICB0aGUgcmVndWxhciBleHByZXNzaW9uIHZhbHVlLCBxdW90ZWQgYXMgaW4gZmll
+bGQgMTAuCgoqKiogRmllbGQgMTAgLSBVc2VyLUlECiAgICBUaGUgdmFsdWUgaXMg
+cXVvdGVkIGxpa2UgYSBDIHN0cmluZyB0byBhdm9pZCBjb250cm9sIGNoYXJhY3Rl
+cnMKICAgICh0aGUgY29sb24gaXMgcXVvdGVkID1ceDNhPSkuICBGb3IgYSAicHVi
+IiByZWNvcmQgdGhpcyBmaWVsZCBpcwogICAgbm90IHVzZWQgb24gLS1maXhlZC1s
+aXN0LW1vZGUuICBBIFVBVCByZWNvcmQgcHV0cyB0aGUgYXR0cmlidXRlCiAgICBz
+dWJwYWNrZXQgY291bnQgaGVyZSwgYSBzcGFjZSwgYW5kIHRoZW4gdGhlIHRvdGFs
+IGF0dHJpYnV0ZQogICAgc3VicGFja2V0IHNpemUuICBJbiBncGdzbSB0aGUgaXNz
+dWVyIG5hbWUgY29tZXMgaGVyZS4gIEEgRlBSCiAgICByZWNvcmQgc3RvcmVzIHRo
+ZSBmaW5nZXJwcmludCBoZXJlLiAgVGhlIGZpbmdlcnByaW50IG9mIGEKICAgIHJl
+dm9jYXRpb24ga2V5IGlzIHN0b3JlZCBoZXJlLgoqKiogRmllbGQgMTEgLSBTaWdu
+YXR1cmUgY2xhc3MKCiAgICBTaWduYXR1cmUgY2xhc3MgYXMgcGVyIFJGQy00ODgw
+LiAgVGhpcyBpcyBhIDIgZGlnaXQgaGV4bnVtYmVyCiAgICBmb2xsb3dlZCBieSBl
+aXRoZXIgdGhlIGxldHRlciAneCcgZm9yIGFuIGV4cG9ydGFibGUgc2lnbmF0dXJl
+IG9yCiAgICB0aGUgbGV0dGVyICdsJyBmb3IgYSBsb2NhbC1vbmx5IHNpZ25hdHVy
+ZS4gIFRoZSBjbGFzcyBieXRlIG9mIGFuCiAgICByZXZvY2F0aW9uIGtleSBpcyBh
+bHNvIGdpdmVuIGhlcmUsICd4JyBhbmQgJ2wnIGlzIHVzZWQgdGhlIHNhbWUKICAg
+IHdheS4gIFRoaXMgZmllbGQgaWYgbm90IHVzZWQgZm9yIFguNTA5LgoKKioqIEZp
+ZWxkIDEyIC0gS2V5IGNhcGFiaWxpdGllcwoKICAgIFRoZSBkZWZpbmVkIGNhcGFi
+aWxpdGllcyBhcmU6CgogICAgLSBlIDo6IEVuY3J5cHQKICAgIC0gcyA6OiBTaWdu
+CiAgICAtIGMgOjogQ2VydGlmeQogICAgLSBhIDo6IEF1dGhlbnRpY2F0aW9uCiAg
+ICAtID8gOjogVW5rbm93biBjYXBhYmlsaXR5CgogICAgQSBrZXkgbWF5IGhhdmUg
+YW55IGNvbWJpbmF0aW9uIG9mIHRoZW0gaW4gYW55IG9yZGVyLiAgSW4gYWRkaXRp
+b24KICAgIHRvIHRoZXNlIGxldHRlcnMsIHRoZSBwcmltYXJ5IGtleSBoYXMgdXBw
+ZXJjYXNlIHZlcnNpb25zIG9mIHRoZQogICAgbGV0dGVycyB0byBkZW5vdGUgdGhl
+IF91c2FibGVfIGNhcGFiaWxpdGllcyBvZiB0aGUgZW50aXJlIGtleSwgYW5kCiAg
+ICBhIHBvdGVudGlhbCBsZXR0ZXIgJ0QnIHRvIGluZGljYXRlIGEgZGlzYWJsZWQg
+a2V5LgoKKioqIEZpZWxkIDEzIC0gSXNzdWVyIGNlcnRpZmljYXRlIGZpbmdlcnBy
+aW50IG9yIG90aGVyIGluZm8KCiAgICBVc2VkIGluIEZQUiByZWNvcmRzIGZvciBT
+L01JTUUga2V5cyB0byBzdG9yZSB0aGUgZmluZ2VycHJpbnQgb2YKICAgIHRoZSBp
+c3N1ZXIgY2VydGlmaWNhdGUuICBUaGlzIGlzIHVzZWZ1bCB0byBidWlsZCB0aGUg
+Y2VydGlmaWNhdGUKICAgIHBhdGggYmFzZWQgb24gY2VydGlmaWNhdGVzIHN0b3Jl
+ZCBpbiB0aGUgbG9jYWwga2V5IGRhdGFiYXNlIGl0IGlzCiAgICBvbmx5IGZpbGxl
+ZCBpZiB0aGUgaXNzdWVyIGNlcnRpZmljYXRlIGlzIGF2YWlsYWJsZS4gVGhlIHJv
+b3QgaGFzCiAgICBiZWVuIHJlYWNoZWQgaWYgdGhpcyBpcyB0aGUgc2FtZSBzdHJp
+bmcgYXMgdGhlIGZpbmdlcnByaW50LiBUaGUKICAgIGFkdmFudGFnZSBvZiB1c2lu
+ZyB0aGlzIHZhbHVlIGlzIHRoYXQgaXQgaXMgZ3VhcmFudGVlZCB0byBoYXZlCiAg
+ICBiZWVuIGJlZW4gYnVpbGQgYnkgdGhlIHNhbWUgbG9va3VwIGFsZ29yaXRobSBh
+cyBncGdzbSB1c2VzLgoKICAgIEZvciAidWlkIiByZWNvcmRzIHRoaXMgZmllbGQg
+bGlzdHMgdGhlIHByZWZlcmVuY2VzIGluIHRoZSBzYW1lIHdheQogICAgZ3BnJ3Mg
+LS1lZGl0LWtleSBtZW51IGRvZXMuCgogICAgRm9yICJzaWciIHJlY29yZHMsIHRo
+aXMgaXMgdGhlIGZpbmdlcnByaW50IG9mIHRoZSBrZXkgdGhhdCBpc3N1ZWQKICAg
+IHRoZSBzaWduYXR1cmUuICBOb3RlIHRoYXQgdGhpcyBpcyBvbmx5IGZpbGxlZCBp
+biBpZiB0aGUgc2lnbmF0dXJlCiAgICB2ZXJpZmllZCBjb3JyZWN0bHkuICBOb3Rl
+IGFsc28gdGhhdCBmb3IgdmFyaW91cyB0ZWNobmljYWwgcmVhc29ucywKICAgIHRo
+aXMgZmluZ2VycHJpbnQgaXMgb25seSBhdmFpbGFibGUgaWYgLS1uby1zaWctY2Fj
+aGUgaXMgdXNlZC4KCioqKiBGaWVsZCAxNCAtIEZsYWcgZmllbGQKCiAgICBGbGFn
+IGZpZWxkIHVzZWQgaW4gdGhlIC0tZWRpdCBtZW51IG91dHB1dAoKKioqIEZpZWxk
+IDE1IC0gUy9OIG9mIGEgdG9rZW4KCiAgICBVc2VkIGluIHNlYy9zc2IgdG8gcHJp
+bnQgdGhlIHNlcmlhbCBudW1iZXIgb2YgYSB0b2tlbiAoaW50ZXJuYWwKICAgIHBy
+b3RlY3QgbW9kZSAxMDAyKSBvciBhICcjJyBpZiB0aGF0IGtleSBpcyBhIHNpbXBs
+ZSBzdHViIChpbnRlcm5hbAogICAgcHJvdGVjdCBtb2RlIDEwMDEpLiAgSWYgdGhl
+IG9wdGlvbiAtLXdpdGgtc2VjcmV0IGlzIHVzZWQgYW5kIGEKICAgIHNlY3JldCBr
+ZXkgaXMgYXZhaWxhYmxlIGZvciB0aGUgcHVibGljIGtleSwgYSAnKycgaW5kaWNh
+dGVzIHRoaXMuCgoqKiogRmllbGQgMTYgLSBIYXNoIGFsZ29yaXRobQoKICAgIEZv
+ciBzaWcgcmVjb3JkcywgdGhpcyBpcyB0aGUgdXNlZCBoYXNoIGFsZ29yaXRobS4g
+IEZvciBleGFtcGxlOgogICAgMiA9IFNIQS0xLCA4ID0gU0hBLTI1Ni4KCioqKiBG
+aWVsZCAxNyAtIEN1cnZlIG5hbWUKCiAgICBGb3IgcHViLCBzdWIsIHNlYywgYW5k
+IHNzYiByZWNvcmRzIHRoaXMgZmllbGQgaXMgdXNlZCBmb3IgdGhlIEVDQwogICAg
+Y3VydmUgbmFtZS4KKioqIEZpZWxkIDE4IC0gVE9GVSBQb2xpY3kKCiAgICBUaGlz
+IGlzIHRoZSBUT0ZVIHBvbGljeS4gIEl0IGlzIGVpdGhlciBnb29kLCBiYWQsIHVu
+a25vd24sIGFzayBvcgogICAgYXV0by4gIFRoaXMgaXMgb25seSBzaG93cyBmb3Ig
+dWlkIHJlY29yZHMuCgoqKiBTcGVjaWFsIGZpZWxkcwoKKioqIFBLRCAtIFB1Ymxp
+YyBrZXkgZGF0YQoKICAgIElmIGZpZWxkIDEgaGFzIHRoZSB0YWcgInBrZCIsIGEg
+bGlzdGluZyBsb29rcyBsaWtlIHRoaXM6CiMrYmVnaW5fZXhhbXBsZQpwa2Q6MDox
+MDI0OkI2NjVCMTQzNUY0QzIgLi4uLiBGRjI2QUJCOgogICAgISAgISAgICEtLSB0
+aGUgdmFsdWUKICAgICEgICEtLS0tLS0gZm9yIGluZm9ybWF0aW9uIG51bWJlciBv
+ZiBiaXRzIGluIHRoZSB2YWx1ZQogICAgIS0tLS0tLS0tLSBpbmRleCAoZWcuIERT
+QSBnb2VzIGZyb20gMCB0byAzOiBwLHEsZyx5KQojK2VuZF9leGFtcGxlCgoqKiog
+VFJVIC0gVHJ1c3QgZGF0YWJhc2UgaW5mb3JtYXRpb24KICAgIEV4YW1wbGUgZm9y
+IGEgInRydSIgdHJ1c3QgYmFzZSByZWNvcmQ6CiMrYmVnaW5fZXhhbXBsZQogICAg
+dHJ1Om86MDoxMTY2Njk3NjU0OjE6MzoxOjUKIytlbmRfZXhhbXBsZQoKICAgIC0g
+RmllbGQgMiA6OiBSZWFzb24gZm9yIHN0YWxlbmVzcyBvZiB0cnVzdC4gIElmIHRo
+aXMgZmllbGQgaXMKICAgICAgICAgICAgICAgICBlbXB0eSwgdGhlbiB0aGUgdHJ1
+c3RkYiBpcyBub3Qgc3RhbGUuICBUaGlzIGZpZWxkIG1heQogICAgICAgICAgICAg
+ICAgIGhhdmUgbXVsdGlwbGUgZmxhZ3MgaW4gaXQ6CgogICAgICAgICAgICAgICAg
+IC0gbyA6OiBUcnVzdGRiIGlzIG9sZAogICAgICAgICAgICAgICAgIC0gdCA6OiBU
+cnVzdGRiIHdhcyBidWlsdCB3aXRoIGEgZGlmZmVyZW50IHRydXN0IG1vZGVsCiAg
+ICAgICAgICAgICAgICAgICAgICAgIHRoYW4gdGhlIG9uZSB3ZSBhcmUgdXNpbmcg
+bm93LgoKICAgIC0gRmllbGQgMyA6OiBUcnVzdCBtb2RlbAoKICAgICAgICAgICAg
+ICAgICAtIDAgOjogQ2xhc3NpYyB0cnVzdCBtb2RlbCwgYXMgdXNlZCBpbiBQR1Ag
+Mi54LgogICAgICAgICAgICAgICAgIC0gMSA6OiBQR1AgdHJ1c3QgbW9kZWwsIGFz
+IHVzZWQgaW4gUEdQIDYgYW5kIGxhdGVyLgogICAgICAgICAgICAgICAgICAgICAg
+ICBUaGlzIGlzIHRoZSBzYW1lIGFzIHRoZSBjbGFzc2ljIHRydXN0IG1vZGVsLAog
+ICAgICAgICAgICAgICAgICAgICAgICBleGNlcHQgZm9yIHRoZSBhZGRpdGlvbiBv
+ZiB0cnVzdCBzaWduYXR1cmVzLgoKICAgICAgICAgICAgICAgICBHbnVQRyBiZWZv
+cmUgdmVyc2lvbiAxLjQgdXNlZCB0aGUgY2xhc3NpYyB0cnVzdCBtb2RlbAogICAg
+ICAgICAgICAgICAgIGJ5IGRlZmF1bHQuIEdudVBHIDEuNCBhbmQgbGF0ZXIgdXNl
+cyB0aGUgUEdQIHRydXN0CiAgICAgICAgICAgICAgICAgbW9kZWwgYnkgZGVmYXVs
+dC4KCiAgICAtIEZpZWxkIDQgOjogRGF0ZSB0cnVzdGRiIHdhcyBjcmVhdGVkIGlu
+IHNlY29uZHMgc2luY2UgRXBvY2guCiAgICAtIEZpZWxkIDUgOjogRGF0ZSB0cnVz
+dGRiIHdpbGwgZXhwaXJlIGluIHNlY29uZHMgc2luY2UgRXBvY2guCiAgICAtIEZp
+ZWxkIDYgOjogTnVtYmVyIG9mIG1hcmdpbmFsbHkgdHJ1c3RlZCB1c2VycyB0byBp
+bnRyb2R1Y2UgYSBuZXcKICAgICAgICAgICAgICAgICBrZXkgc2lnbmVyIChncGcn
+cyBvcHRpb24gLS1tYXJnaW5hbHMtbmVlZGVkKS4KICAgIC0gRmllbGQgNyA6OiBO
+dW1iZXIgb2YgY29tcGxldGVseSB0cnVzdGVkIHVzZXJzIHRvIGludHJvZHVjZSBh
+IG5ldwogICAgICAgICAgICAgICAgIGtleSBzaWduZXIuICAoZ3BnJ3Mgb3B0aW9u
+IC0tY29tcGxldGVzLW5lZWRlZCkKCiAgICAtIEZpZWxkIDggOjogTWF4aW11bSBk
+ZXB0aCBvZiBhIGNlcnRpZmljYXRpb24gY2hhaW4uIChncGcncyBvcHRpb24KICAg
+ICAgICAgICAgICAgICAtLW1heC1jZXJ0LWRlcHRoKQoKKioqIFNQSyAtIFNpZ25h
+dHVyZSBzdWJwYWNrZXQgcmVjb3JkcwoKICAgIC0gRmllbGQgMiA6OiBTdWJwYWNr
+ZXQgbnVtYmVyIGFzIHBlciBSRkMtNDg4MCBhbmQgbGF0ZXIuCiAgICAtIEZpZWxk
+IDMgOjogRmxhZ3MgaW4gaGV4LiAgQ3VycmVudGx5IHRoZSBvbmx5IHR3byBiaXRz
+IGFzc2lnbmVkCiAgICAgICAgICAgICAgICAgYXJlIDEsIHRvIGluZGljYXRlIHRo
+YXQgdGhlIHN1YnBhY2tldCBjYW1lIGZyb20gdGhlCiAgICAgICAgICAgICAgICAg
+aGFzaGVkIHBhcnQgb2YgdGhlIHNpZ25hdHVyZSwgYW5kIDIsIHRvIGluZGljYXRl
+IHRoZQogICAgICAgICAgICAgICAgIHN1YnBhY2tldCB3YXMgbWFya2VkIGNyaXRp
+Y2FsLgogICAgLSBGaWVsZCA0IDo6IExlbmd0aCBvZiB0aGUgc3VicGFja2V0LiAg
+Tm90ZSB0aGF0IHRoaXMgaXMgdGhlCiAgICAgICAgICAgICAgICAgbGVuZ3RoIG9m
+IHRoZSBzdWJwYWNrZXQsIGFuZCBub3QgdGhlIGxlbmd0aCBvZiBmaWVsZAogICAg
+ICAgICAgICAgICAgIDUgYmVsb3cuICBEdWUgdG8gdGhlIG5lZWQgZm9yICUtZW5j
+b2RpbmcsIHRoZSBsZW5ndGgKICAgICAgICAgICAgICAgICBvZiBmaWVsZCA1IG1h
+eSBiZSB1cCB0byAzeCB0aGlzIHZhbHVlLgogICAgLSBGaWVsZCA1IDo6IFRoZSBz
+dWJwYWNrZXQgZGF0YS4gIFByaW50YWJsZSBBU0NJSSBpcyBzaG93biBhcwogICAg
+ICAgICAgICAgICAgIEFTQ0lJLCBidXQgb3RoZXIgdmFsdWVzIGFyZSByZW5kZXJl
+ZCBhcyAlWFggd2hlcmUgWFgKICAgICAgICAgICAgICAgICBpcyB0aGUgaGV4IHZh
+bHVlIGZvciB0aGUgYnl0ZS4KCioqKiBDRkcgLSBDb25maWd1cmF0aW9uIGRhdGEK
+CiAgICAtLWxpc3QtY29uZmlnIG91dHB1dHMgaW5mb3JtYXRpb24gYWJvdXQgdGhl
+IEdudVBHIGNvbmZpZ3VyYXRpb24KICAgIGZvciB0aGUgYmVuZWZpdCBvZiBmcm9u
+dGVuZHMgb3Igb3RoZXIgcHJvZ3JhbXMgdGhhdCBjYWxsIEdudVBHLgogICAgVGhl
+cmUgYXJlIHNldmVyYWwgbGlzdC1jb25maWcgaXRlbXMsIGFsbCBjb2xvbiBkZWxp
+bWl0ZWQgbGlrZSB0aGUKICAgIHJlc3Qgb2YgdGhlIC0td2l0aC1jb2xvbnMgb3V0
+cHV0LiAgVGhlIGZpcnN0IGZpZWxkIGlzIGFsd2F5cyAiY2ZnIgogICAgdG8gaW5k
+aWNhdGUgY29uZmlndXJhdGlvbiBpbmZvcm1hdGlvbi4gIFRoZSBzZWNvbmQgZmll
+bGQgaXMgb25lIG9mCiAgICAod2l0aCBleGFtcGxlcyk6CgogICAgLSB2ZXJzaW9u
+IDo6IFRoZSB0aGlyZCBmaWVsZCBjb250YWlucyB0aGUgdmVyc2lvbiBvZiBHbnVQ
+Ry4KCiAgICAgICAgICAgICAgICAgOiBjZmc6dmVyc2lvbjoxLjMuNQoKICAgIC0g
+cHVia2V5IDo6IFRoZSB0aGlyZCBmaWVsZCBjb250YWlucyB0aGUgcHVibGljIGtl
+eSBhbGdvcml0aG1zCiAgICAgICAgICAgICAgICB0aGlzIHZlcnNpb24gb2YgR251
+UEcgc3VwcG9ydHMsIHNlcGFyYXRlZCBieQogICAgICAgICAgICAgICAgc2VtaWNv
+bG9ucy4gIFRoZSBhbGdvcml0aG0gbnVtYmVycyBhcmUgYXMgc3BlY2lmaWVkIGlu
+CiAgICAgICAgICAgICAgICBSRkMtNDg4MC4gIE5vdGUgdGhhdCBpbiBjb250cmFz
+dCB0byB0aGUgLS1zdGF0dXMtZmQKICAgICAgICAgICAgICAgIGludGVyZmFjZSB0
+aGVzZSBhcmUgX25vdF8gdGhlIExpYmdjcnlwdCBpZGVudGlmaWVycy4KICAgICAg
+ICAgICAgICAgIFVzaW5nID1wdWJrZXluYW1lPSBwcmludHMgbmFtZXMgaW5zdGVh
+ZCBvZiBudW1iZXJzLgoKICAgICAgICAgICAgICAgICA6IGNmZzpwdWJrZXk6MTsy
+OzM7MTY7MTcKCiAgICAtIGNpcGhlciA6OiBUaGUgdGhpcmQgZmllbGQgY29udGFp
+bnMgdGhlIHN5bW1ldHJpYyBjaXBoZXJzIHRoaXMKICAgICAgICAgICAgICAgIHZl
+cnNpb24gb2YgR251UEcgc3VwcG9ydHMsIHNlcGFyYXRlZCBieSBzZW1pY29sb25z
+LgogICAgICAgICAgICAgICAgVGhlIGNpcGhlciBudW1iZXJzIGFyZSBhcyBzcGVj
+aWZpZWQgaW4gUkZDLTQ4ODAuCiAgICAgICAgICAgICAgICBVc2luZyA9Y2lwaGVy
+bmFtZT0gcHJpbnRzIG5hbWVzIGluc3RlYWQgb2YgbnVtYmVycy4KCiAgICAgICAg
+ICAgICAgICAgOiBjZmc6Y2lwaGVyOjI7Mzs0Ozc7ODs5OzEwCgogICAgLSBkaWdl
+c3QgOjogVGhlIHRoaXJkIGZpZWxkIGNvbnRhaW5zIHRoZSBkaWdlc3QgKGhhc2gp
+IGFsZ29yaXRobXMKICAgICAgICAgICAgICAgIHRoaXMgdmVyc2lvbiBvZiBHbnVQ
+RyBzdXBwb3J0cywgc2VwYXJhdGVkIGJ5CiAgICAgICAgICAgICAgICBzZW1pY29s
+b25zLiAgVGhlIGRpZ2VzdCBudW1iZXJzIGFyZSBhcyBzcGVjaWZpZWQgaW4KICAg
+ICAgICAgICAgICAgIFJGQy00ODgwLiAgVXNpbmcgPWRpZ2VzdG5hbWU9IHByaW50
+cyBuYW1lcyBpbnN0ZWFkIG9mCiAgICAgICAgICAgICAgICBudW1iZXJzLgoKICAg
+ICAgICAgICAgICAgICA6IGNmZzpkaWdlc3Q6MTsyOzM7ODs5OzEwCgogICAgLSBj
+b21wcmVzcyA6OiBUaGUgdGhpcmQgZmllbGQgY29udGFpbnMgdGhlIGNvbXByZXNz
+aW9uIGFsZ29yaXRobXMKICAgICAgICAgICAgICAgICAgdGhpcyB2ZXJzaW9uIG9m
+IEdudVBHIHN1cHBvcnRzLCBzZXBhcmF0ZWQgYnkKICAgICAgICAgICAgICAgICAg
+c2VtaWNvbG9ucy4gIFRoZSBhbGdvcml0aG0gbnVtYmVycyBhcmUgYXMgc3BlY2lm
+aWVkCiAgICAgICAgICAgICAgICAgIGluIFJGQy00ODgwLgoKICAgICAgICAgICAg
+ICAgICA6IGNmZzpjb21wcmVzczowOzE7MjszCgogICAgLSBncm91cCA6OiBUaGUg
+dGhpcmQgZmllbGQgY29udGFpbnMgdGhlIG5hbWUgb2YgdGhlIGdyb3VwLCBhbmQg
+dGhlCiAgICAgICAgICAgICAgIGZvdXJ0aCBmaWVsZCBjb250YWlucyB0aGUgdmFs
+dWVzIHRoYXQgdGhlIGdyb3VwIGV4cGFuZHMKICAgICAgICAgICAgICAgdG8sIHNl
+cGFyYXRlZCBieSBzZW1pY29sb25zLgoKICAgICAgICAgICAgICAgRm9yIGV4YW1w
+bGUsIGEgZ3JvdXAgb2Y6CiAgICAgICAgICAgICAgICAgOiBncm91cCBteW5hbWVz
+ID0gcGFpZ2UgMHgxMjM0NTY3OCBqb2UgcGF0dGkKICAgICAgICAgICAgICAgd291
+bGQgcmVzdWx0IGluOgogICAgICAgICAgICAgICAgIDogY2ZnOmdyb3VwOm15bmFt
+ZXM6cGF0dGk7am9lOzB4MTIzNDU2Nzg7cGFpZ2UKCiAgICAtIGN1cnZlIDo6IFRo
+ZSB0aGlyZCBmaWVsZCBjb250YWlucyB0aGUgY3VydmUgbmFtZXMgdGhpcyB2ZXJz
+aW9uCiAgICAgICAgICAgICAgIG9mIEdudVBHIHN1cHBvcnRzLCBzZXBhcmF0ZWQg
+Ynkgc2VtaWNvbG9ucy4gVXNpbmcKICAgICAgICAgICAgICAgPWN1cnZlb2lkPSBw
+cmludHMgT0lEcyBpbnN0ZWFkIG9mIG51bWJlcnMuCgogICAgICAgICAgICAgICAg
+IDogY2ZnOmN1cnZlOmVkMjU1MTk7bmlzdHAyNTY7bmlzdHAzODQ7bmlzdHA1MjEK
+CgoqIEZvcm1hdCBvZiB0aGUgLS1zdGF0dXMtZmQgb3V0cHV0CgogIEV2ZXJ5IGxp
+bmUgaXMgcHJlZml4ZWQgd2l0aCAiW0dOVVBHOl0gIiwgZm9sbG93ZWQgYnkgYSBr
+ZXl3b3JkIHdpdGgKICB0aGUgdHlwZSBvZiB0aGUgc3RhdHVzIGxpbmUgYW5kIHNv
+bWUgYXJndW1lbnRzIGRlcGVuZGluZyBvbiB0aGUgdHlwZQogIChtYXliZSBub25l
+KTsgYW4gYXBwbGljYXRpb24gc2hvdWxkIGFsd2F5cyBiZSBwcmVwYXJlZCB0byBz
+ZWUgbW9yZQogIGFyZ3VtZW50cyBpbiBmdXR1cmUgdmVyc2lvbnMuCgoqKiBHZW5l
+cmFsIHN0YXR1cyBjb2RlcwoqKiogTkVXU0lHCiAgICBJcyBpc3N1ZWQgcmlnaHQg
+YmVmb3JlIGEgc2lnbmF0dXJlIHZlcmlmaWNhdGlvbiBzdGFydHMuICBUaGlzIGlz
+CiAgICB1c2VmdWwgdG8gZGVmaW5lIGEgY29udGV4dCBmb3IgcGFyc2luZyBFUlJP
+UiBzdGF0dXMgbWVzc2FnZXMuICBObwogICAgYXJndW1lbnRzIGFyZSBjdXJyZW50
+bHkgZGVmaW5lZC4KCioqKiBHT09EU0lHICA8bG9uZ19rZXlpZF9vcl9mcHI+ICA8
+dXNlcm5hbWU+CiAgICBUaGUgc2lnbmF0dXJlIHdpdGggdGhlIGtleWlkIGlzIGdv
+b2QuICBGb3IgZWFjaCBzaWduYXR1cmUgb25seSBvbmUKICAgIG9mIHRoZSBjb2Rl
+cyBHT09EU0lHLCBCQURTSUcsIEVYUFNJRywgRVhQS0VZU0lHLCBSRVZLRVlTSUcg
+b3IKICAgIEVSUlNJRyB3aWxsIGJlIGVtaXR0ZWQuICBJbiB0aGUgcGFzdCB0aGV5
+IHdlcmUgdXNlZCBhcyBhIG1hcmtlcgogICAgZm9yIGEgbmV3IHNpZ25hdHVyZTsg
+bmV3IGNvZGUgc2hvdWxkIHVzZSB0aGUgTkVXU0lHIHN0YXR1cwogICAgaW5zdGVh
+ZC4gIFRoZSB1c2VybmFtZSBpcyB0aGUgcHJpbWFyeSBvbmUgZW5jb2RlZCBpbiBV
+VEYtOCBhbmQgJVhYCiAgICBlc2NhcGVkLiBUaGUgZmluZ2VycHJpbnQgbWF5IGJl
+IHVzZWQgaW5zdGVhZCBvZiB0aGUgbG9uZyBrZXlpZCBpZgogICAgaXQgaXMgYXZh
+aWxhYmxlLiAgVGhpcyBpcyB0aGUgY2FzZSB3aXRoIENNUyBhbmQgbWlnaHQgZXZl
+bnR1YWxseQogICAgYWxzbyBiZSBhdmFpbGFibGUgZm9yIE9wZW5QR1AuCgoqKiog
+RVhQU0lHICA8bG9uZ19rZXlpZF9vcl9mcHI+ICA8dXNlcm5hbWU+CiAgICBUaGUg
+c2lnbmF0dXJlIHdpdGggdGhlIGtleWlkIGlzIGdvb2QsIGJ1dCB0aGUgc2lnbmF0
+dXJlIGlzCiAgICBleHBpcmVkLiBUaGUgdXNlcm5hbWUgaXMgdGhlIHByaW1hcnkg
+b25lIGVuY29kZWQgaW4gVVRGLTggYW5kICVYWAogICAgZXNjYXBlZC4gVGhlIGZp
+bmdlcnByaW50IG1heSBiZSB1c2VkIGluc3RlYWQgb2YgdGhlIGxvbmcga2V5aWQg
+aWYKICAgIGl0IGlzIGF2YWlsYWJsZS4gIFRoaXMgaXMgdGhlIGNhc2Ugd2l0aCBD
+TVMgYW5kIG1pZ2h0IGV2ZW50dWFsbHkKICAgIGFsc28gYmUgYXZhaWxhYmxlIGZv
+ciBPcGVuUEdQLgoKKioqIEVYUEtFWVNJRyAgPGxvbmdfa2V5aWRfb3JfZnByPiA8
+dXNlcm5hbWU+CiAgICBUaGUgc2lnbmF0dXJlIHdpdGggdGhlIGtleWlkIGlzIGdv
+b2QsIGJ1dCB0aGUgc2lnbmF0dXJlIHdhcyBtYWRlCiAgICBieSBhbiBleHBpcmVk
+IGtleS4gVGhlIHVzZXJuYW1lIGlzIHRoZSBwcmltYXJ5IG9uZSBlbmNvZGVkIGlu
+CiAgICBVVEYtOCBhbmQgJVhYIGVzY2FwZWQuICBUaGUgZmluZ2VycHJpbnQgbWF5
+IGJlIHVzZWQgaW5zdGVhZCBvZiB0aGUKICAgIGxvbmcga2V5aWQgaWYgaXQgaXMg
+YXZhaWxhYmxlLiAgVGhpcyBpcyB0aGUgY2FzZSB3aXRoIENNUyBhbmQKICAgIG1p
+Z2h0IGV2ZW50dWFsbHkgYWxzbyBiZSBhdmFpbGFibGUgZm9yIE9wZW5QR1AuCgoq
+KiogUkVWS0VZU0lHICA8bG9uZ19rZXlpZF9vcl9mcHI+ICA8dXNlcm5hbWU+CiAg
+ICBUaGUgc2lnbmF0dXJlIHdpdGggdGhlIGtleWlkIGlzIGdvb2QsIGJ1dCB0aGUg
+c2lnbmF0dXJlIHdhcyBtYWRlCiAgICBieSBhIHJldm9rZWQga2V5LiBUaGUgdXNl
+cm5hbWUgaXMgdGhlIHByaW1hcnkgb25lIGVuY29kZWQgaW4gVVRGLTgKICAgIGFu
+ZCAlWFggZXNjYXBlZC4gVGhlIGZpbmdlcnByaW50IG1heSBiZSB1c2VkIGluc3Rl
+YWQgb2YgdGhlIGxvbmcKICAgIGtleWlkIGlmIGl0IGlzIGF2YWlsYWJsZS4gIFRo
+aXMgaXMgdGhlIGNhc2Ugd2l0aCBDTVMgYW5kIG1pZ2h0CiAgICBldmVudHVhbGx5
+IGFsc28gYmXDsSBhdmFpbGFibGUgZm9yIE9wZW5QR1AuCgoqKiogQkFEU0lHICA8
+bG9uZ19rZXlpZF9vcl9mcHI+ICA8dXNlcm5hbWU+CiAgICBUaGUgc2lnbmF0dXJl
+IHdpdGggdGhlIGtleWlkIGhhcyBub3QgYmVlbiB2ZXJpZmllZCBva2F5LiAgVGhl
+CiAgICB1c2VybmFtZSBpcyB0aGUgcHJpbWFyeSBvbmUgZW5jb2RlZCBpbiBVVEYt
+OCBhbmQgJVhYIGVzY2FwZWQuIFRoZQogICAgZmluZ2VycHJpbnQgbWF5IGJlIHVz
+ZWQgaW5zdGVhZCBvZiB0aGUgbG9uZyBrZXlpZCBpZiBpdCBpcwogICAgYXZhaWxh
+YmxlLiAgVGhpcyBpcyB0aGUgY2FzZSB3aXRoIENNUyBhbmQgbWlnaHQgZXZlbnR1
+YWxseSBhbHNvIGJlCiAgICBhdmFpbGFibGUgZm9yIE9wZW5QR1AuCgoqKiogRVJS
+U0lHICA8a2V5aWQ+ICA8cGthbGdvPiA8aGFzaGFsZ28+IDxzaWdfY2xhc3M+IDx0
+aW1lPiA8cmM+CiAgICBJdCB3YXMgbm90IHBvc3NpYmxlIHRvIGNoZWNrIHRoZSBz
+aWduYXR1cmUuICBUaGlzIG1heSBiZSBjYXVzZWQgYnkKICAgIGEgbWlzc2luZyBw
+dWJsaWMga2V5IG9yIGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobS4gIEEgUkMgb2Yg
+NAogICAgaW5kaWNhdGVzIHVua25vd24gYWxnb3JpdGhtLCBhIDkgaW5kaWNhdGVz
+IGEgbWlzc2luZyBwdWJsaWMKICAgIGtleS4gVGhlIG90aGVyIGZpZWxkcyBnaXZl
+IG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgdGhpcyBzaWduYXR1cmUuCiAgICBzaWdf
+Y2xhc3MgaXMgYSAyIGJ5dGUgaGV4LXZhbHVlLiAgVGhlIGZpbmdlcnByaW50IG1h
+eSBiZSB1c2VkCiAgICBpbnN0ZWFkIG9mIHRoZSBrZXlpZCBpZiBpdCBpcyBhdmFp
+bGFibGUuICBUaGlzIGlzIHRoZSBjYXNlIHdpdGgKICAgIGdwZ3NtIGFuZCBtaWdo
+dCBldmVudHVhbGx5IGFsc28gYmUgYXZhaWxhYmxlIGZvciBPcGVuUEdQLgoKICAg
+IE5vdGUsIHRoYXQgVElNRSBtYXkgZWl0aGVyIGJlIHRoZSBudW1iZXIgb2Ygc2Vj
+b25kcyBzaW5jZSBFcG9jaCBvcgogICAgYW4gSVNPIDg2MDEgc3RyaW5nLiAgVGhl
+IGxhdHRlciBjYW4gYmUgZGV0ZWN0ZWQgYnkgdGhlIHByZXNlbmNlIG9mCiAgICB0
+aGUgbGV0dGVyICdUJy4KCioqKiBWQUxJRFNJRyA8YXJncz4KCiAgICBUaGUgYXJn
+cyBhcmU6CgogICAgLSA8ZmluZ2VycHJpbnRfaW5faGV4PgogICAgLSA8c2lnX2Ny
+ZWF0aW9uX2RhdGU+CiAgICAtIDxzaWctdGltZXN0YW1wPgogICAgLSA8ZXhwaXJl
+LXRpbWVzdGFtcD4KICAgIC0gPHNpZy12ZXJzaW9uPgogICAgLSA8cmVzZXJ2ZWQ+
+CiAgICAtIDxwdWJrZXktYWxnbz4KICAgIC0gPGhhc2gtYWxnbz4KICAgIC0gPHNp
+Zy1jbGFzcz4KICAgIC0gWyA8cHJpbWFyeS1rZXktZnByPiBdCgogICAgVGhpcyBz
+dGF0dXMgaW5kaWNhdGVzIHRoYXQgdGhlIHNpZ25hdHVyZSBpcyBjcnlwdG9ncmFw
+aGljYWxseQogICAgdmFsaWQuIFRoaXMgaXMgc2ltaWxhciB0byBHT09EU0lHLCBF
+WFBTSUcsIEVYUEtFWVNJRywgb3IgUkVWS0VZU0lHCiAgICAoZGVwZW5kaW5nIG9u
+IHRoZSBkYXRlIGFuZCB0aGUgc3RhdGUgb2YgdGhlIHNpZ25hdHVyZSBhbmQgc2ln
+bmluZwogICAga2V5KSBidXQgaGFzIHRoZSBmaW5nZXJwcmludCBhcyB0aGUgYXJn
+dW1lbnQuIE11bHRpcGxlIHN0YXR1cwogICAgbGluZXMgKFZBTElEU0lHIGFuZCB0
+aGUgb3RoZXIgYXBwcm9wcmlhdGUgKlNJRyBzdGF0dXMpIGFyZSBlbWl0dGVkCiAg
+ICBmb3IgYSB2YWxpZCBzaWduYXR1cmUuICBBbGwgYXJndW1lbnRzIGhlcmUgYXJl
+IG9uIG9uZSBsb25nIGxpbmUuCiAgICBzaWctdGltZXN0YW1wIGlzIHRoZSBzaWdu
+YXR1cmUgY3JlYXRpb24gdGltZSBpbiBzZWNvbmRzIGFmdGVyIHRoZQogICAgZXBv
+Y2guIGV4cGlyZS10aW1lc3RhbXAgaXMgdGhlIHNpZ25hdHVyZSBleHBpcmF0aW9u
+IHRpbWUgaW4KICAgIHNlY29uZHMgYWZ0ZXIgdGhlIGVwb2NoICh6ZXJvIG1lYW5z
+ICJkb2VzIG5vdAogICAgZXhwaXJlIikuIHNpZy12ZXJzaW9uLCBwdWJrZXktYWxn
+bywgaGFzaC1hbGdvLCBhbmQgc2lnLWNsYXNzIChhCiAgICAyLWJ5dGUgaGV4IHZh
+bHVlKSBhcmUgYWxsIHN0cmFpZ2h0IGZyb20gdGhlIHNpZ25hdHVyZSBwYWNrZXQu
+CiAgICBQUklNQVJZLUtFWS1GUFIgaXMgdGhlIGZpbmdlcnByaW50IG9mIHRoZSBw
+cmltYXJ5IGtleSBvciBpZGVudGljYWwKICAgIHRvIHRoZSBmaXJzdCBhcmd1bWVu
+dC4gIFRoaXMgaXMgdXNlZnVsIHRvIGdldCBiYWNrIHRvIHRoZSBwcmltYXJ5CiAg
+ICBrZXkgd2l0aG91dCBydW5uaW5nIGdwZyBhZ2FpbiBmb3IgdGhpcyBwdXJwb3Nl
+LgoKICAgIFRoZSBwcmltYXJ5LWtleS1mcHIgcGFyYW1ldGVyIGlzIHVzZWQgZm9y
+IE9wZW5QR1AgYW5kIG5vdAogICAgYXZhaWxhYmxlIGZvciBDTVMgc2lnbmF0dXJl
+cy4gIFRoZSBzaWctdmVyc2lvbiBhcyB3ZWxsIGFzIHRoZSBzaWcKICAgIGNsYXNz
+IGlzIG5vdCBkZWZpbmVkIGZvciBDTVMgYW5kIGN1cnJlbnRseSBzZXQgdG8gMCBh
+bmQgMDAuCgogICAgTm90ZSwgdGhhdCAqLVRJTUVTVEFNUCBtYXkgZWl0aGVyIGJl
+IGEgbnVtYmVyIG9mIHNlY29uZHMgc2luY2UKICAgIEVwb2NoIG9yIGFuIElTTyA4
+NjAxIHN0cmluZyB3aGljaCBjYW4gYmUgZGV0ZWN0ZWQgYnkgdGhlIHByZXNlbmNl
+CiAgICBvZiB0aGUgbGV0dGVyICdUJy4KCioqKiBTSUdfSUQgIDxyYWRpeDY0X3N0
+cmluZz4gIDxzaWdfY3JlYXRpb25fZGF0ZT4gIDxzaWctdGltZXN0YW1wPgogICAg
+VGhpcyBpcyBlbWl0dGVkIG9ubHkgZm9yIHNpZ25hdHVyZXMgb2YgY2xhc3MgMCBv
+ciAxIHdoaWNoIGhhdmUKICAgIGJlZW4gdmVyaWZpZWQgb2theS4gIFRoZSBzdHJp
+bmcgaXMgYSBzaWduYXR1cmUgaWQgYW5kIG1heSBiZSB1c2VkCiAgICBpbiBhcHBs
+aWNhdGlvbnMgdG8gZGV0ZWN0IHJlcGxheSBhdHRhY2tzIG9mIHNpZ25lZCBtZXNz
+YWdlcy4gIE5vdGUKICAgIHRoYXQgb25seSBETFAgYWxnb3JpdGhtcyBnaXZlIHVu
+aXF1ZSBpZHMgLSBvdGhlcnMgbWF5IHlpZWxkCiAgICBkdXBsaWNhdGVkIG9uZXMg
+d2hlbiB0aGV5IGhhdmUgYmVlbiBjcmVhdGVkIGluIHRoZSBzYW1lIHNlY29uZC4K
+CiAgICBOb3RlLCB0aGF0IFNJRy1USU1FU1RBTVAgbWF5IGVpdGhlciBiZSBhIG51
+bWJlciBvZiBzZWNvbmRzIHNpbmNlCiAgICBFcG9jaCBvciBhbiBJU08gODYwMSBz
+dHJpbmcgd2hpY2ggY2FuIGJlIGRldGVjdGVkIGJ5IHRoZSBwcmVzZW5jZQogICAg
+b2YgdGhlIGxldHRlciAnVCcuCgoqKiogRU5DX1RPICA8bG9uZ19rZXlpZD4gIDxr
+ZXl0eXBlPiAgPGtleWxlbmd0aD4KICAgIFRoZSBtZXNzYWdlIGlzIGVuY3J5cHRl
+ZCB0byB0aGlzIExPTkdfS0VZSUQuICBLRVlUWVBFIGlzIHRoZQogICAgbnVtZXJp
+Y2FsIHZhbHVlIG9mIHRoZSBwdWJsaWMga2V5IGFsZ29yaXRobSBvciAwIGlmIGl0
+IGlzIG5vdAogICAga25vd24sIEtFWUxFTkdUSCBpcyB0aGUgbGVuZ3RoIG9mIHRo
+ZSBrZXkgb3IgMCBpZiBpdCBpcyBub3Qga25vd24KICAgICh3aGljaCBpcyBjdXJy
+ZW50bHkgYWx3YXlzIHRoZSBjYXNlKS4gIEdwZyBwcmludHMgdGhpcyBsaW5lCiAg
+ICBhbHdheXM7IEdwZ3NtIG9ubHkgaWYgaXQga25vd3MgdGhlIGNlcnRpZmljYXRl
+LgoKKioqIEJFR0lOX0RFQ1JZUFRJT04KICAgIE1hcmsgdGhlIHN0YXJ0IG9mIHRo
+ZSBhY3R1YWwgZGVjcnlwdGlvbiBwcm9jZXNzLiAgVGhpcyBpcyBhbHNvCiAgICBl
+bWl0dGVkIHdoZW4gaW4gLS1saXN0LW9ubHkgbW9kZS4KKioqIEVORF9ERUNSWVBU
+SU9OCiAgICBNYXJrIHRoZSBlbmQgb2YgdGhlIGFjdHVhbCBkZWNyeXB0aW9uIHBy
+b2Nlc3MuICBUaGlzIGFyZSBhbHNvCiAgICBlbWl0dGVkIHdoZW4gaW4gLS1saXN0
+LW9ubHkgbW9kZS4KKioqIERFQ1JZUFRJT05fSU5GTyA8bWRjX21ldGhvZD4gPHN5
+bV9hbGdvPgogICAgUHJpbnQgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHN5bW1ldHJp
+YyBlbmNyeXB0aW9uIGFsZ29yaXRobSBhbmQgdGhlCiAgICBNREMgbWV0aG9kLiAg
+VGhpcyB3aWxsIGJlIGVtaXR0ZWQgZXZlbiBpZiB0aGUgZGVjcnlwdGlvbiBmYWls
+cy4KCioqKiBERUNSWVBUSU9OX0ZBSUxFRAogICAgVGhlIHN5bW1ldHJpYyBkZWNy
+eXB0aW9uIGZhaWxlZCAtIG9uZSByZWFzb24gY291bGQgYmUgYSB3cm9uZwogICAg
+cGFzc3BocmFzZSBmb3IgYSBzeW1tZXRyaWNhbCBlbmNyeXB0ZWQgbWVzc2FnZS4K
+CioqKiBERUNSWVBUSU9OX09LQVkKICAgIFRoZSBkZWNyeXB0aW9uIHByb2Nlc3Mg
+c3VjY2VlZGVkLiAgVGhpcyBtZWFucywgdGhhdCBlaXRoZXIgdGhlCiAgICBjb3Jy
+ZWN0IHNlY3JldCBrZXkgaGFzIGJlZW4gdXNlZCBvciB0aGUgY29ycmVjdCBwYXNz
+cGhyYXNlIGZvciBhCiAgICBzeW1tZXRyaWMgZW5jcnlwdGVkIG1lc3NhZ2Ugd2Fz
+IGdpdmVuLiAgVGhlIHByb2dyYW0gaXRzZWxmIG1heQogICAgcmV0dXJuIGFuIGVy
+cm9yY29kZSBiZWNhdXNlIGl0IG1heSBub3QgYmUgcG9zc2libGUgdG8gdmVyaWZ5
+IGEKICAgIHNpZ25hdHVyZSBmb3Igc29tZSByZWFzb25zLgoKKioqIFNFU1NJT05f
+S0VZIDxhbGdvPjo8aGV4ZGlnaXRzPgogICAgVGhlIHNlc3Npb24ga2V5IHVzZWQg
+dG8gZGVjcnlwdCB0aGUgbWVzc2FnZS4gIFRoaXMgbWVzc2FnZSB3aWxsCiAgICBv
+bmx5IGJlIGVtaXR0ZWQgaWYgdGhlIG9wdGlvbiAtLXNob3ctc2Vzc2lvbi1rZXkg
+aXMgdXNlZC4gIFRoZQogICAgZm9ybWF0IGlzIHN1aXRhYmxlIHRvIGJlIHBhc3Nl
+ZCBhcyB2YWx1ZSBmb3IgdGhlIG9wdGlvbgogICAgLS1vdmVycmlkZS1zZXNzaW9u
+LWtleS4gIEl0IGlzIG5vdCBhbiBpbmRpY2F0aW9uIHRoYXQgdGhlCiAgICBkZWNy
+eXB0aW9uIHdpbGwgb3IgaGFzIHN1Y2NlZWRlZC4KCioqKiBCRUdJTl9FTkNSWVBU
+SU9OICA8bWRjX21ldGhvZD4gPHN5bV9hbGdvPgogICAgTWFyayB0aGUgc3RhcnQg
+b2YgdGhlIGFjdHVhbCBlbmNyeXB0aW9uIHByb2Nlc3MuCgoqKiogRU5EX0VOQ1JZ
+UFRJT04KICAgIE1hcmsgdGhlIGVuZCBvZiB0aGUgYWN0dWFsIGVuY3J5cHRpb24g
+cHJvY2Vzcy4KCioqKiBGSUxFX1NUQVJUIDx3aGF0PiA8ZmlsZW5hbWU+CiAgICBT
+dGFydCBwcm9jZXNzaW5nIGEgZmlsZSA8ZmlsZW5hbWU+LiAgPHdoYXQ+IGluZGlj
+YXRlcyB0aGUgcGVyZm9ybWVkCiAgICBvcGVyYXRpb246CiAgICAtIDEgOjogdmVy
+aWZ5CiAgICAtIDIgOjogZW5jcnlwdAogICAgLSAzIDo6IGRlY3J5cHQKCioqKiBG
+SUxFX0RPTkUKICAgIE1hcmtzIHRoZSBlbmQgb2YgYSBmaWxlIHByb2Nlc3Npbmcg
+d2hpY2ggaGFzIGJlZW4gc3RhcnRlZAogICAgYnkgRklMRV9TVEFSVC4KCioqKiBC
+RUdJTl9TSUdOSU5HCiAgICBNYXJrIHRoZSBzdGFydCBvZiB0aGUgYWN0dWFsIHNp
+Z25pbmcgcHJvY2Vzcy4gVGhpcyBtYXkgYmUgdXNlZCBhcwogICAgYW4gaW5kaWNh
+dGlvbiB0aGF0IGFsbCByZXF1ZXN0ZWQgc2VjcmV0IGtleXMgYXJlIHJlYWR5IGZv
+ciB1c2UuCgoqKiogQUxSRUFEWV9TSUdORUQgPGxvbmcta2V5aWQ+CiAgICBXYXJu
+aW5nOiBUaGlzIGlzIGV4cGVyaW1lbnRhbCBhbmQgbWlnaHQgYmUgcmVtb3ZlZCBh
+dCBhbnkgdGltZS4KCioqKiBTSUdfQ1JFQVRFRCA8dHlwZT4gPHBrX2FsZ28+IDxo
+YXNoX2FsZ28+IDxjbGFzcz4gPHRpbWVzdGFtcD4gPGtleWZwcj4KICAgIEEgc2ln
+bmF0dXJlIGhhcyBiZWVuIGNyZWF0ZWQgdXNpbmcgdGhlc2UgcGFyYW1ldGVycy4K
+ICAgIFZhbHVlcyBmb3IgdHlwZSA8dHlwZT4gYXJlOgogICAgICAtIEQgOjogZGV0
+YWNoZWQKICAgICAgLSBDIDo6IGNsZWFydGV4dAogICAgICAtIFMgOjogc3RhbmRh
+cmQKICAgIChvbmx5IHRoZSBmaXJzdCBjaGFyYWN0ZXIgc2hvdWxkIGJlIGNoZWNr
+ZWQpCgogICAgPGNsYXNzPiBhcmUgMiBoZXggZGlnaXRzIHdpdGggdGhlIE9wZW5Q
+R1Agc2lnbmF0dXJlIGNsYXNzLgoKICAgIE5vdGUsIHRoYXQgVElNRVNUQU1QIG1h
+eSBlaXRoZXIgYmUgYSBudW1iZXIgb2Ygc2Vjb25kcyBzaW5jZSBFcG9jaAogICAg
+b3IgYW4gSVNPIDg2MDEgc3RyaW5nIHdoaWNoIGNhbiBiZSBkZXRlY3RlZCBieSB0
+aGUgcHJlc2VuY2Ugb2YgdGhlCiAgICBsZXR0ZXIgJ1QnLgoKKioqIE5PVEFUSU9O
+XwogICAgVGhlcmUgYXJlIGFjdHVhbGx5IHR3byByZWxhdGVkIHN0YXR1cyBjb2Rl
+cyB0byBjb252ZXkgbm90YXRpb24KICAgIGRhdGE6CgogICAgLSBOT1RBVElPTl9O
+QU1FIDxuYW1lPgogICAgLSBOT1RBVElPTl9EQVRBIDxzdHJpbmc+CgogICAgPG5h
+bWU+IGFuZCA8c3RyaW5nPiBhcmUgJVhYIGVzY2FwZWQ7IHRoZSBkYXRhIG1heSBi
+ZSBzcGxpdCBhbW9uZwogICAgc2V2ZXJhbCBOT1RBVElPTl9EQVRBIGxpbmVzLgoK
+KioqIFBPTElDWV9VUkwgPHN0cmluZz4KICAgIE5vdGUgdGhhdCBVUkwgaW4gPHN0
+cmluZz4gaXMgJVhYIGVzY2FwZWQuCgoqKiogUExBSU5URVhUIDxmb3JtYXQ+IDx0
+aW1lc3RhbXA+IDxmaWxlbmFtZT4KICAgIFRoaXMgaW5kaWNhdGVzIHRoZSBmb3Jt
+YXQgb2YgdGhlIHBsYWludGV4dCB0aGF0IGlzIGFib3V0IHRvIGJlCiAgICB3cml0
+dGVuLiAgVGhlIGZvcm1hdCBpcyBhIDEgYnl0ZSBoZXggY29kZSB0aGF0IHNob3dz
+IHRoZSBmb3JtYXQgb2YKICAgIHRoZSBwbGFpbnRleHQ6IDYyICgnYicpIGlzIGJp
+bmFyeSBkYXRhLCA3NCAoJ3QnKSBpcyB0ZXh0IGRhdGEgd2l0aAogICAgbm8gY2hh
+cmFjdGVyIHNldCBzcGVjaWZpZWQsIGFuZCA3NSAoJ3UnKSBpcyB0ZXh0IGRhdGEg
+ZW5jb2RlZCBpbgogICAgdGhlIFVURi04IGNoYXJhY3RlciBzZXQuICBUaGUgdGlt
+ZXN0YW1wIGlzIGluIHNlY29uZHMgc2luY2UgdGhlCiAgICBlcG9jaC4gIElmIGEg
+ZmlsZW5hbWUgaXMgYXZhaWxhYmxlIGl0IGdldHMgcHJpbnRlZCBhcyB0aGUgdGhp
+cmQKICAgIGFyZ3VtZW50LCBwZXJjZW50LWVzY2FwZWQgYXMgdXN1YWwuCgoqKiog
+UExBSU5URVhUX0xFTkdUSCA8bGVuZ3RoPgogICAgVGhpcyBpbmRpY2F0ZXMgdGhl
+IGxlbmd0aCBvZiB0aGUgcGxhaW50ZXh0IHRoYXQgaXMgYWJvdXQgdG8gYmUKICAg
+IHdyaXR0ZW4uICBOb3RlIHRoYXQgaWYgdGhlIHBsYWludGV4dCBwYWNrZXQgaGFz
+IHBhcnRpYWwgbGVuZ3RoCiAgICBlbmNvZGluZyBpdCBpcyBub3QgcG9zc2libGUg
+dG8ga25vdyB0aGUgbGVuZ3RoIGFoZWFkIG9mIHRpbWUuICBJbgogICAgdGhhdCBj
+YXNlLCB0aGlzIHN0YXR1cyB0YWcgZG9lcyBub3QgYXBwZWFyLgoKKioqIEFUVFJJ
+QlVURSA8YXJndW1lbnRzPgogICAgVGhlIGxpc3Qgb3IgYXJnZW1udHMgYXJlOgog
+ICAgLSA8ZnByPgogICAgLSA8b2N0ZXRzPgogICAgLSA8dHlwZT4KICAgIC0gPGlu
+ZGV4PgogICAgLSA8Y291bnQ+CiAgICAtIDx0aW1lc3RhbXA+CiAgICAtIDxleHBp
+cmVkYXRlPgogICAgLSA8ZmxhZ3M+CgogICAgVGhpcyBpcyBvbmUgbG9uZyBsaW5l
+IGlzc3VlZCBmb3IgZWFjaCBhdHRyaWJ1dGUgc3VicGFja2V0IHdoZW4gYW4KICAg
+IGF0dHJpYnV0ZSBwYWNrZXQgaXMgc2VlbiBkdXJpbmcga2V5IGxpc3RpbmcuICA8
+ZnByPiBpcyB0aGUKICAgIGZpbmdlcnByaW50IG9mIHRoZSBrZXkuICA8b2N0ZXRz
+PiBpcyB0aGUgbGVuZ3RoIG9mIHRoZSBhdHRyaWJ1dGUKICAgIHN1YnBhY2tldC4g
+IDx0eXBlPiBpcyB0aGUgYXR0cmlidXRlIHR5cGUgKGUuZy4gMSBmb3IgYW4gaW1h
+Z2UpLgogICAgPGluZGV4PiBhbmQgPGNvdW50PiBpbmRpY2F0ZSB0aGF0IHRoaXMg
+aXMgdGhlIE4tdGggaW5kZXhlZAogICAgc3VicGFja2V0IG9mIGNvdW50IHRvdGFs
+IHN1YnBhY2tldHMgaW4gdGhpcyBhdHRyaWJ1dGUgcGFja2V0LgogICAgPHRpbWVz
+dGFtcD4gYW5kIDxleHBpcmVkYXRlPiBhcmUgZnJvbSB0aGUgc2VsZi1zaWduYXR1
+cmUgb24gdGhlCiAgICBhdHRyaWJ1dGUgcGFja2V0LiAgSWYgdGhlIGF0dHJpYnV0
+ZSBwYWNrZXQgZG9lcyBub3QgaGF2ZSBhIHZhbGlkCiAgICBzZWxmLXNpZ25hdHVy
+ZSwgdGhlbiB0aGUgdGltZXN0YW1wIGlzIDAuICA8ZmxhZ3M+IGFyZSBhIGJpdHdp
+c2UgT1IKICAgIG9mOgogICAgLSAweDAxIDo6IHRoaXMgYXR0cmlidXRlIHBhY2tl
+dCBpcyBhIHByaW1hcnkgdWlkCiAgICAtIDB4MDIgOjogdGhpcyBhdHRyaWJ1dGUg
+cGFja2V0IGlzIHJldm9rZWQKICAgIC0gMHgwNCA6OiB0aGlzIGF0dHJpYnV0ZSBw
+YWNrZXQgaXMgZXhwaXJlZAoKKioqIFNJR19TVUJQQUNLRVQgPHR5cGU+IDxmbGFn
+cz4gPGxlbj4gPGRhdGE+CiAgICBUaGlzIGluZGljYXRlcyB0aGF0IGEgc2lnbmF0
+dXJlIHN1YnBhY2tldCB3YXMgc2Vlbi4gIFRoZSBmb3JtYXQgaXMKICAgIHRoZSBz
+YW1lIGFzIHRoZSAic3BrIiByZWNvcmQgYWJvdmUuCgoqKiBLZXkgcmVsYXRlZAoq
+KiogSU5WX1JFQ1AsIElOVl9TR05SCiAgICBUaGUgdHdvIHNpbWlsYXIgc3RhdHVz
+IGNvZGVzOgoKICAgIC0gSU5WX1JFQ1AgPHJlYXNvbj4gPHJlcXVlc3RlZF9yZWNp
+cGllbnQ+CiAgICAtIElOVl9TR05SIDxyZWFzb24+IDxyZXF1ZXN0ZWRfc2VuZGVy
+PgoKICAgIGFyZSBpc3N1ZWQgZm9yIGVhY2ggdW51c2FibGUgcmVjaXBpZW50L3Nl
+bmRlci4gVGhlIHJlYXNvbnMgY29kZXMKICAgIGN1cnJlbnRseSBpbiB1c2UgYXJl
+OgoKICAgICAgIC0gIDAgOjogTm8gc3BlY2lmaWMgcmVhc29uIGdpdmVuCiAgICAg
+ICAtICAxIDo6IE5vdCBGb3VuZAogICAgICAgLSAgMiA6OiBBbWJpZ2lvdXMgc3Bl
+Y2lmaWNhdGlvbgogICAgICAgLSAgMyA6OiBXcm9uZyBrZXkgdXNhZ2UKICAgICAg
+IC0gIDQgOjogS2V5IHJldm9rZWQKICAgICAgIC0gIDUgOjogS2V5IGV4cGlyZWQK
+ICAgICAgIC0gIDYgOjogTm8gQ1JMIGtub3duCiAgICAgICAtICA3IDo6IENSTCB0
+b28gb2xkCiAgICAgICAtICA4IDo6IFBvbGljeSBtaXNtYXRjaAogICAgICAgLSAg
+OSA6OiBOb3QgYSBzZWNyZXQga2V5CiAgICAgICAtIDEwIDo6IEtleSBub3QgdHJ1
+c3RlZAogICAgICAgLSAxMSA6OiBNaXNzaW5nIGNlcnRpZmljYXRlCiAgICAgICAt
+IDEyIDo6IE1pc3NpbmcgaXNzdWVyIGNlcnRpZmljYXRlCiAgICAgICAtIDEzIDo6
+IEtleSBkaXNhYmxlZAogICAgICAgLSAxNCA6OiBTeW50YXggZXJyb3IgaW4gc3Bl
+Y2lmaWNhdGlvbgoKICAgIE5vdGUgdGhhdCBmb3IgaGlzdG9yaWNhbCByZWFzb25z
+IHRoZSBJTlZfUkVDUCBzdGF0dXMgaXMgYWxzbyB1c2VkCiAgICBmb3IgZ3Bnc20n
+cyBTSUdORVIgY29tbWFuZCB3aGVyZSBpdCByZWxhdGVzIHRvIHNpZ25lcidzIG9m
+IGNvdXJzZS4KICAgIE5ld2VyIEdudVBHIHZlcnNpb25zIGFyZSB1c2luZyBJTlZf
+U0dOUjsgYXBwbGljYXRpb25zIHNob3VsZAogICAgaWdub3JlIHRoZSBJTlZfUkVD
+UCBkdXJpbmcgdGhlIHNlbmRlcidzIGNvbW1hbmQgcHJvY2Vzc2luZyBvbmNlCiAg
+ICB0aGV5IGhhdmUgc2VlbiBhbiBJTlZfU0dOUi4gIERpZmZlcmVudCBjb2RlcyBh
+cmUgdXNlZCBzbyB0aGF0IHRoZXkKICAgIGNhbiBiZSBkaXN0aW5ndWlzaCB3aGls
+ZSBkb2luZyBhbiBlbmNyeXB0K3NpZ24gb3BlcmF0aW9uLgoqKiogTk9fUkVDUCA8
+cmVzZXJ2ZWQ+CiAgICBJc3N1ZWQgaWYgbm8gcmVjaXBpZW50cyBhcmUgdXNhYmxl
+LgoKKioqIE5PX1NHTlIgPHJlc2VydmVkPgogICAgSXNzdWVkIGlmIG5vIHNlbmRl
+cnMgYXJlIHVzYWJsZS4KCioqKiBLRVlFWFBJUkVEIDxleHBpcmUtdGltZXN0YW1w
+PgogICAgVGhlIGtleSBoYXMgZXhwaXJlZC4gIGV4cGlyZS10aW1lc3RhbXAgaXMg
+dGhlIGV4cGlyYXRpb24gdGltZSBpbgogICAgc2Vjb25kcyBzaW5jZSBFcG9jaC4g
+IFRoaXMgc3RhdHVzIGxpbmUgaXMgbm90IHZlcnkgdXNlZnVsIGJlY2F1c2UKICAg
+IGl0IHdpbGwgYWxzbyBiZSBlbWl0dGVkIGZvciBleHBpcmVkIHN1YmtleXMgZXZl
+biBpZiB0aGlzIHN1YmtleSBpcwogICAgbm90IHVzZWQuICBUbyBjaGVjayB3aGV0
+aGVyIGEga2V5IHVzZWQgdG8gc2lnbiBhIG1lc3NhZ2UgaGFzCiAgICBleHBpcmVk
+LCB0aGUgRVhQS0VZU0lHIHN0YXR1cyBsaW5lIGlzIHRvIGJlIHVzZWQuCgogICAg
+Tm90ZSwgdGhhdCB0aGUgVElNRVNUQU1QIG1heSBlaXRoZXIgYmUgYSBudW1iZXIg
+b2Ygc2Vjb25kcyBzaW5jZQogICAgRXBvY2ggb3IgYW4gSVNPIDg2MDEgc3RyaW5n
+IHdoaWNoIGNhbiBiZSBkZXRlY3RlZCBieSB0aGUgcHJlc2VuY2UKICAgIG9mIHRo
+ZSBsZXR0ZXIgJ1QnLgoKKioqIEtFWVJFVk9LRUQKICAgIFRoZSB1c2VkIGtleSBo
+YXMgYmVlbiByZXZva2VkIGJ5IGl0cyBvd25lci4gIE5vIGFyZ3VtZW50cyB5ZXQu
+CgoqKiogTk9fUFVCS0VZICA8bG9uZyBrZXlpZD4KICAgIFRoZSBwdWJsaWMga2V5
+IGlzIG5vdCBhdmFpbGFibGUKCioqKiBOT19TRUNLRVkgIDxsb25nIGtleWlkPgog
+ICAgVGhlIHNlY3JldCBrZXkgaXMgbm90IGF2YWlsYWJsZQoKKioqIEtFWV9DUkVB
+VEVEIDx0eXBlPiA8ZmluZ2VycHJpbnQ+IFs8aGFuZGxlPl0KICAgIEEga2V5IGhh
+cyBiZWVuIGNyZWF0ZWQuICBWYWx1ZXMgZm9yIDx0eXBlPiBhcmU6CiAgICAgIC0g
+QiA6OiBwcmltYXJ5IGFuZCBzdWJrZXkKICAgICAgLSBQIDo6IHByaW1hcnkKICAg
+ICAgLSBTIDo6IHN1YmtleQogICAgVGhlIGZpbmdlcnByaW50IGlzIG9uZSBvZiB0
+aGUgcHJpbWFyeSBrZXkgZm9yIHR5cGUgQiBhbmQgUCBhbmQgdGhlCiAgICBvbmUg
+b2YgdGhlIHN1YmtleSBmb3IgUy4gIEhhbmRsZSBpcyBhbiBhcmJpdHJhcnkgbm9u
+LXdoaXRlc3BhY2UKICAgIHN0cmluZyB1c2VkIHRvIG1hdGNoIGtleSBwYXJhbWV0
+ZXJzIGZyb20gYmF0Y2gga2V5IGNyZWF0aW9uIHJ1bi4KCioqKiBLRVlfTk9UX0NS
+RUFURUQgWzxoYW5kbGU+XQogICAgVGhlIGtleSBmcm9tIGJhdGNoIHJ1biBoYXMg
+bm90IGJlZW4gY3JlYXRlZCBkdWUgdG8gZXJyb3JzLgoKKioqIFRSVVNUXwogICAg
+VGhlc2UgYXJlIHNldmVyYWwgc2ltaWxhciBzdGF0dXMgY29kZXM6CgogICAgLSBU
+UlVTVF9VTkRFRklORUQgPGVycm9yX3Rva2VuPgogICAgLSBUUlVTVF9ORVZFUiAg
+ICAgPGVycm9yX3Rva2VuPgogICAgLSBUUlVTVF9NQVJHSU5BTCAgWzAgIFs8dmFs
+aWRhdGlvbl9tb2RlbD5dXQogICAgLSBUUlVTVF9GVUxMWSAgICAgWzAgIFs8dmFs
+aWRhdGlvbl9tb2RlbD5dXQogICAgLSBUUlVTVF9VTFRJTUFURSAgWzAgIFs8dmFs
+aWRhdGlvbl9tb2RlbD5dXQoKICAgIEZvciBnb29kIHNpZ25hdHVyZXMgb25lIG9m
+IHRoZXNlIHN0YXR1cyBsaW5lcyBhcmUgZW1pdHRlZCB0bwogICAgaW5kaWNhdGUg
+dGhlIHZhbGlkaXR5IG9mIHRoZSBrZXkgdXNlZCB0byBjcmVhdGUgdGhlIHNpZ25h
+dHVyZS4KICAgIFRoZSBlcnJvciB0b2tlbiB2YWx1ZXMgYXJlIGN1cnJlbnRseSBv
+bmx5IGVtaXR0ZWQgYnkgZ3Bnc20uCgogICAgVkFMSURBVElPTl9NT0RFTCBkZXNj
+cmliZXMgdGhlIGFsZ29yaXRobSB1c2VkIHRvIGNoZWNrIHRoZQogICAgdmFsaWRp
+dHkgb2YgdGhlIGtleS4gIFRoZSBkZWZhdWx0cyBhcmUgdGhlIHN0YW5kYXJkIFdl
+YiBvZiBUcnVzdAogICAgbW9kZWwgZm9yIGdwZyBhbmQgdGhlIHRoZSBzdGFuZGFy
+ZCBYLjUwOSBtb2RlbCBmb3IgZ3Bnc20uICBUaGUKICAgIGRlZmluZWQgdmFsdWVz
+IGFyZQoKICAgICAgIC0gcGdwICAgOjogVGhlIHN0YW5kYXJkIFBHUCBXb1QuCiAg
+ICAgICAtIHNoZWxsIDo6IFRoZSBzdGFuZGFyZCBYLjUwOSBtb2RlbC4KICAgICAg
+IC0gY2hhaW4gOjogVGhlIGNoYWluIG1vZGVsLgogICAgICAgLSBzdGVlZCA6OiBU
+aGUgU1RFRUQgbW9kZWwuCgogICAgTm90ZSB0aGF0IHRoZSB0ZXJtID1UUlVTVF89
+IGluIHRoZSBzdGF0dXMgbmFtZXMgaXMgdXNlZCBmb3IKICAgIGhpc3RvcmljIHJl
+YXNvbnM7IHdlIG5vdyBzcGVhayBvZiB2YWxpZGl0eS4KCioqKiBQS0FfVFJVU1Rf
+CiAgICBUaGlzIGlzIGlzIG9uZToKCiAgICAtIFBLQV9UUlVTVF9HT09EIDxtYWls
+Ym94PgogICAgLSBQS0FfVFJVU1RfQkFEICA8bWFpbGJveD4KCiAgICBEZXBlbmRp
+bmcgb24gdGhlIG91dGNvbWUgb2YgdGhlIFBLQSBjaGVjayBvbmUgb2YgdGhlIGFi
+b3ZlIHN0YXR1cwogICAgY29kZXMgaXMgZW1pdHRlZCBpbiBhZGRpdGlvbiB0byBh
+ID1UUlVTVF8qPSBzdGF0dXMuCgoqKiBSZW1vdGUgY29udHJvbAoqKiogR0VUX0JP
+T0wsIEdFVF9MSU5FLCBHRVRfSElEREVOLCBHT1RfSVQKCiAgICBUaGVzZSBzdGF0
+dXMgbGluZSBhcmUgdXNlZCB3aXRoIC0tY29tbWFuZC1mZCBmb3IgaW50ZXJhY3Rp
+dmUKICAgIGNvbnRyb2wgb2YgdGhlIHByb2Nlc3MuCgoqKiogVVNFUklEX0hJTlQg
+PGxvbmcgbWFpbiBrZXlpZD4gPHN0cmluZz4KICAgIEdpdmUgYSBoaW50IGFib3V0
+IHRoZSB1c2VyIElEIGZvciBhIGNlcnRhaW4ga2V5SUQuCgoqKiogTkVFRF9QQVNT
+UEhSQVNFIDxsb25nIGtleWlkPiA8bG9uZyBtYWluIGtleWlkPiA8a2V5dHlwZT4g
+PGtleWxlbmd0aD4KICAgIElzc3VlZCB3aGVuZXZlciBhIHBhc3NwaHJhc2UgaXMg
+bmVlZGVkLiAgS0VZVFlQRSBpcyB0aGUgbnVtZXJpY2FsCiAgICB2YWx1ZSBvZiB0
+aGUgcHVibGljIGtleSBhbGdvcml0aG0gb3IgMCBpZiB0aGlzIGlzIG5vdCBhcHBs
+aWNhYmxlLAogICAgS0VZTEVOR1RIIGlzIHRoZSBsZW5ndGggb2YgdGhlIGtleSBv
+ciAwIGlmIGl0IGlzIG5vdCBrbm93biAodGhpcwogICAgaXMgY3VycmVudGx5IGFs
+d2F5cyB0aGUgY2FzZSkuCgoqKiogTkVFRF9QQVNTUEhSQVNFX1NZTSA8Y2lwaGVy
+X2FsZ28+IDxzMmtfbW9kZT4gPHMya19oYXNoPgogICAgSXNzdWVkIHdoZW5ldmVy
+IGEgcGFzc3BocmFzZSBmb3Igc3ltbWV0cmljIGVuY3J5cHRpb24gaXMgbmVlZGVk
+LgoKKioqIE5FRURfUEFTU1BIUkFTRV9QSU4gPGNhcmRfdHlwZT4gPGNodm5vPiBb
+PHNlcmlhbG5vPl0KICAgIElzc3VlZCB3aGVuZXZlciBhIFBJTiBpcyByZXF1ZXN0
+ZWQgdG8gdW5sb2NrIGEgY2FyZC4KCioqKiBNSVNTSU5HX1BBU1NQSFJBU0UKICAg
+IE5vIHBhc3NwaHJhc2Ugd2FzIHN1cHBsaWVkLiAgQW4gYXBwbGljYXRpb24gd2hp
+Y2ggZW5jb3VudGVycyB0aGlzCiAgICBtZXNzYWdlIG1heSB3YW50IHRvIHN0b3Ag
+cGFyc2luZyBpbW1lZGlhdGVseSBiZWNhdXNlIHRoZSBuZXh0CiAgICBtZXNzYWdl
+IHdpbGwgcHJvYmFibHkgYmUgYSBCQURfUEFTU1BIUkFTRS4gIEhvd2V2ZXIsIGlm
+IHRoZQogICAgYXBwbGljYXRpb24gaXMgYSB3cmFwcGVyIGFyb3VuZCB0aGUga2V5
+IGVkaXQgbWVudSBmdW5jdGlvbmFsaXR5IGl0CiAgICBtaWdodCBub3QgbWFrZSBz
+ZW5zZSB0byBzdG9wIHBhcnNpbmcgYnV0IHNpbXBseSBpZ25vcmluZyB0aGUKICAg
+IGZvbGxvd2luZyBCQURfUEFTU1BIUkFTRS4KCioqKiBCQURfUEFTU1BIUkFTRSA8
+bG9uZyBrZXlpZD4KICAgIFRoZSBzdXBwbGllZCBwYXNzcGhyYXNlIHdhcyB3cm9u
+ZyBvciBub3QgZ2l2ZW4uICBJbiB0aGUgbGF0dGVyCiAgICBjYXNlIHlvdSBtYXkg
+aGF2ZSBzZWVuIGEgTUlTU0lOR19QQVNTUEhSQVNFLgoKKioqIEdPT0RfUEFTU1BI
+UkFTRQogICAgVGhlIHN1cHBsaWVkIHBhc3NwaHJhc2Ugd2FzIGdvb2QgYW5kIHRo
+ZSBzZWNyZXQga2V5IG1hdGVyaWFsCiAgICBpcyB0aGVyZWZvcmUgdXNhYmxlLgoK
+KiogSW1wb3J0L0V4cG9ydAoqKiogSU1QT1JUX0NIRUNLIDxsb25nIGtleWlkPiA8
+ZmluZ2VycHJpbnQ+IDx1c2VyIElEPgogICAgVGhpcyBzdGF0dXMgaXMgZW1pdHRl
+ZCBpbiBpbnRlcmFjdGl2ZSBtb2RlIHJpZ2h0IGJlZm9yZQogICAgdGhlICJpbXBv
+cnQub2theSIgcHJvbXB0LgoKKioqIElNUE9SVEVEICAgPGxvbmcga2V5aWQ+ICA8
+dXNlcm5hbWU+CiAgICBUaGUga2V5aWQgYW5kIG5hbWUgb2YgdGhlIHNpZ25hdHVy
+ZSBqdXN0IGltcG9ydGVkCgoqKiogSU1QT1JUX09LICA8cmVhc29uPiBbPGZpbmdl
+cnByaW50Pl0KICAgIFRoZSBrZXkgd2l0aCB0aGUgcHJpbWFyeSBrZXkncyBGSU5H
+RVJQUklOVCBoYXMgYmVlbiBpbXBvcnRlZC4KICAgIFJFQVNPTiBmbGFncyBhcmU6
+CgogICAgLSAwIDo6IE5vdCBhY3R1YWxseSBjaGFuZ2VkCiAgICAtIDEgOjogRW50
+aXJlbHkgbmV3IGtleS4KICAgIC0gMiA6OiBOZXcgdXNlciBJRHMKICAgIC0gNCA6
+OiBOZXcgc2lnbmF0dXJlcwogICAgLSA4IDo6IE5ldyBzdWJrZXlzCiAgICAtIDE2
+IDo6IENvbnRhaW5zIHByaXZhdGUga2V5LgoKICAgIFRoZSBmbGFncyBtYXkgYmUg
+T1JlZC4KCioqKiBJTVBPUlRfUFJPQkxFTSA8cmVhc29uPiBbPGZpbmdlcnByaW50
+Pl0KICAgIElzc3VlZCBmb3IgZWFjaCBpbXBvcnQgZmFpbHVyZS4gIFJlYXNvbiBj
+b2RlcyBhcmU6CgogICAgLSAwIDo6IE5vIHNwZWNpZmljIHJlYXNvbiBnaXZlbi4K
+ICAgIC0gMSA6OiBJbnZhbGlkIENlcnRpZmljYXRlLgogICAgLSAyIDo6IElzc3Vl
+ciBDZXJ0aWZpY2F0ZSBtaXNzaW5nLgogICAgLSAzIDo6IENlcnRpZmljYXRlIENo
+YWluIHRvbyBsb25nLgogICAgLSA0IDo6IEVycm9yIHN0b3JpbmcgY2VydGlmaWNh
+dGUuCgoqKiogSU1QT1JUX1JFUyA8YXJncz4KICAgIEZpbmFsIHN0YXRpc3RpY3Mg
+b24gaW1wb3J0IHByb2Nlc3MgKHRoaXMgaXMgb25lIGxvbmcgbGluZSkuIFRoZQog
+ICAgYXJncyBhcmUgYSBsaXN0IG9mIHVuc2lnbmVkIG51bWJlcnMgc2VwYXJhdGVk
+IGJ5IHdoaXRlIHNwYWNlOgoKICAgIC0gPGNvdW50PgogICAgLSA8bm9fdXNlcl9p
+ZD4KICAgIC0gPGltcG9ydGVkPgogICAgLSBhbHdheXMgMCAoZm9ybWVybHkgdXNl
+ZCBmb3IgdGhlIG51bWJlciBvZiBSU0Ega2V5cykKICAgIC0gPHVuY2hhbmdlZD4K
+ICAgIC0gPG5fdWlkcz4KICAgIC0gPG5fc3Viaz4KICAgIC0gPG5fc2lncz4KICAg
+IC0gPG5fcmV2b2M+CiAgICAtIDxzZWNfcmVhZD4KICAgIC0gPHNlY19pbXBvcnRl
+ZD4KICAgIC0gPHNlY19kdXBzPgogICAgLSA8c2tpcHBlZF9uZXdfa2V5cz4KICAg
+IC0gPG5vdF9pbXBvcnRlZD4KICAgIC0gPHNraXBwZWRfdjNfa2V5cz4KCioqKiBF
+WFBPUlRFRCAgPGZpbmdlcnByaW50PgogICAgVGhlIGtleSB3aXRoIDxmaW5nZXJw
+cmludD4gaGFzIGJlZW4gZXhwb3J0ZWQuICBUaGUgZmluZ2VycHJpbnQgaXMKICAg
+IHRoZSBmaW5nZXJwcmludCBvZiB0aGUgcHJpbWFyeSBrZXkgZXZlbiBpZiB0aGUg
+cHJpbWFyeSBrZXkgaGFzCiAgICBiZWVuIHJlcGxhY2VkIGJ5IGEgc3R1YiBrZXkg
+ZHVyaW5nIHNlY3JldCBrZXkgZXhwb3J0LgoKKioqIEVYUE9SVF9SRVMgPGFyZ3M+
+CgogICAgRmluYWwgc3RhdGlzdGljcyBvbiBleHBvcnQgcHJvY2VzcyAodGhpcyBp
+cyBvbmUgbG9uZyBsaW5lKS4gVGhlCiAgICBhcmdzIGFyZSBhIGxpc3Qgb2YgdW5z
+aWduZWQgbnVtYmVycyBzZXBhcmF0ZWQgYnkgd2hpdGUgc3BhY2U6CgogICAgLSA8
+Y291bnQ+CiAgICAtIDxzZWNyZXRfY291bnQ+CiAgICAtIDxleHBvcnRlZD4KCgoq
+KiBTbWFydGNhcmQgcmVsYXRlZAoqKiogQ0FSRENUUkwgPHdoYXQ+IFs8c2VyaWFs
+bm8+XQogICAgVGhpcyBpcyB1c2VkIHRvIGNvbnRyb2wgc21hcnRjYXJkIG9wZXJh
+dGlvbnMuICBEZWZpbmVkIHZhbHVlcyBmb3IKICAgIFdIQVQgYXJlOgoKICAgICAg
+LSAxIDo6IFJlcXVlc3QgaW5zZXJ0aW9uIG9mIGEgY2FyZC4gIFNlcmlhbG51bWJl
+ciBtYXkgYmUgZ2l2ZW4KICAgICAgICAgICAgIHRvIHJlcXVlc3QgYSBzcGVjaWZp
+YyBjYXJkLiAgVXNlZCBieSBncGcgMS40IHcvbwogICAgICAgICAgICAgc2NkYWVt
+b24KICAgICAgLSAyIDo6IFJlcXVlc3QgcmVtb3ZhbCBvZiBhIGNhcmQuICBVc2Vk
+IGJ5IGdwZyAxLjQgdy9vIHNjZGFlbW9uLgogICAgICAtIDMgOjogQ2FyZCB3aXRo
+IHNlcmlhbG51bWJlciBkZXRlY3RlZAogICAgICAtIDQgOjogTm8gY2FyZCBhdmFp
+bGFibGUKICAgICAgLSA1IDo6IE5vIGNhcmQgcmVhZGVyIGF2YWlsYWJsZQogICAg
+ICAtIDYgOjogTm8gY2FyZCBzdXBwb3J0IGF2YWlsYWJsZQogICAgICAtIDcgOjog
+Q2FyZCBpcyBpbiB0ZXJtaW5hdGlvbiBzdGF0ZQoKKioqIFNDX09QX0ZBSUxVUkUg
+Wzxjb2RlPl0KICAgIEFuIG9wZXJhdGlvbiBvbiBhIHNtYXJ0Y2FyZCBkZWZpbml0
+ZWx5IGZhaWxlZC4gIEN1cnJlbnRseSB0aGVyZSBpcwogICAgbm8gaW5kaWNhdGlv
+biBvZiB0aGUgYWN0dWFsIGVycm9yIGNvZGUsIGJ1dCBhcHBsaWNhdGlvbiBzaG91
+bGQgYmUKICAgIHByZXBhcmVkIHRvIGxhdGVyIGFjY2VwdCBtb3JlIGFyZ3VtZW50
+cy4gIERlZmluZWQgdmFsdWVzIGZvcgogICAgPGNvZGU+IGFyZToKCiAgICAgIC0g
+MCA6OiB1bnNwZWNpZmllZCBlcnJvciAoaWRlbnRpY2FsbHkgdG8gYSBtaXNzaW5n
+IENPREUpCiAgICAgIC0gMSA6OiBjYW5jZWxlZAogICAgICAtIDIgOjogYmFkIFBJ
+TgoKKioqIFNDX09QX1NVQ0NFU1MKICAgIEEgc21hcnQgY2FyZCBvcGVyYWlvbiBz
+dWNjZWVkZWQuICBUaGlzIHN0YXR1cyBpcyBvbmx5IHByaW50ZWQgZm9yCiAgICBj
+ZXJ0YWluIG9wZXJhdGlvbiBhbmQgaXMgbW9zdGx5IHVzZWZ1bCB0byBjaGVjayB3
+aGV0aGVyIGEgUElOCiAgICBjaGFuZ2UgcmVhbGx5IHdvcmtlZC4KCioqIE1pc2Nl
+bGxhbmVvdXMgc3RhdHVzIGNvZGVzCioqKiBOT0RBVEEgIDx3aGF0PgogICAgTm8g
+ZGF0YSBoYXMgYmVlbiBmb3VuZC4gIENvZGVzIGZvciBXSEFUIGFyZToKCiAgICAt
+IDEgOjogTm8gYXJtb3JlZCBkYXRhLgogICAgLSAyIDo6IEV4cGVjdGVkIGEgcGFj
+a2V0IGJ1dCBkaWQgbm90IGZvdW5kIG9uZS4KICAgIC0gMyA6OiBJbnZhbGlkIHBh
+Y2tldCBmb3VuZCwgdGhpcyBtYXkgaW5kaWNhdGUgYSBub24gT3BlblBHUAogICAg
+ICAgICAgIG1lc3NhZ2UuCiAgICAtIDQgOjogU2lnbmF0dXJlIGV4cGVjdGVkIGJ1
+dCBub3QgZm91bmQKCiAgICBZb3UgbWF5IHNlZSBtb3JlIHRoYW4gb25lIG9mIHRo
+ZXNlIHN0YXR1cyBsaW5lcy4KCioqKiBVTkVYUEVDVEVEIDx3aGF0PgogICAgVW5l
+eHBlY3RlZCBkYXRhIGhhcyBiZWVuIGVuY291bnRlcmVkLiAgQ29kZXMgZm9yIFdI
+QVQgYXJlOgogICAgLSAwIDo6IE5vdCBmdXJ0aGVyIHNwZWNpZmllZAogICAgLSAx
+IDo6IENvcnJ1cHRlZCBtZXNzYWdlIHN0cnVjdHVyZQoKKioqIFRSVU5DQVRFRCA8
+bWF4bm8+CiAgICBUaGUgb3V0cHV0IHdhcyB0cnVuY2F0ZWQgdG8gTUFYTk8gaXRl
+bXMuICBUaGlzIHN0YXR1cyBjb2RlIGlzCiAgICBpc3N1ZWQgZm9yIGNlcnRhaW4g
+ZXh0ZXJuYWwgcmVxdWVzdHMuCgoqKiogRVJST1IgPGVycm9yIGxvY2F0aW9uPiA8
+ZXJyb3IgY29kZT4gWzxtb3JlPl0KICAgIFRoaXMgaXMgYSBnZW5lcmljIGVycm9y
+IHN0YXR1cyBtZXNzYWdlLCBpdCBtaWdodCBiZSBmb2xsb3dlZCBieQogICAgZXJy
+b3IgbG9jYXRpb24gc3BlY2lmaWMgZGF0YS4gPGVycm9yIGNvZGU+IGFuZCA8ZXJy
+b3JfbG9jYXRpb24+CiAgICBzaG91bGQgbm90IGNvbnRhaW4gc3BhY2VzLiAgVGhl
+IGVycm9yIGNvZGUgaXMgYSBlaXRoZXIgYSBzdHJpbmcKICAgIGNvbW1lbmNpbmcg
+d2l0aCBhIGxldHRlciBvciBzdWNoIGEgc3RyaW5nIHByZWZpeGVkIHdpdGggYQog
+ICAgbnVtZXJpY2FsIGVycm9yIGNvZGUgYW5kIGFuIHVuZGVyc2NvcmU7IGUuZy46
+ICIxNTEwMTEzMjdfRU9GIi4KKioqIFdBUk5JTkcgPGxvY2F0aW9uPiA8ZXJyb3Ig
+Y29kZT4gWzx0ZXh0Pl0KICAgIFRoaXMgaXMgYSBnZW5lcmljIHdhcm5pbmcgc3Rh
+dHVzIG1lc3NhZ2UsIGl0IG1pZ2h0IGJlIGZvbGxvd2VkIGJ5CiAgICBlcnJvciBs
+b2NhdGlvbiBzcGVjaWZpYyBkYXRhLiA8ZXJyb3IgY29kZT4gYW5kIDxsb2NhdGlv
+bj4KICAgIHNob3VsZCBub3QgY29udGFpbiBzcGFjZXMuICBUaGUgZXJyb3IgY29k
+ZSBpcyBhIGVpdGhlciBhIHN0cmluZwogICAgY29tbWVuY2luZyB3aXRoIGEgbGV0
+dGVyIG9yIHN1Y2ggYSBzdHJpbmcgcHJlZml4ZWQgd2l0aCBhCiAgICBudW1lcmlj
+YWwgZXJyb3IgY29kZSBhbmQgYW4gdW5kZXJzY29yZTsgZS5nLjogIjE1MTAxMTMy
+N19FT0YiLgoqKiogU1VDQ0VTUyBbPGxvY2F0aW9uPl0KICAgIFBvc3RpdmUgY29u
+ZmlybWF0aW9uIHRoYXQgYW4gb3BlcmF0aW9uIHN1Y2NlZWRlZC4gIEl0IGlzIHVz
+ZWQKICAgIHNpbWlsYXIgdG8gSVNPLUMncyBFWElUX1NVQ0NFU1MuICA8bG9jYXRp
+b24+IGlzIG9wdGlvbmFsIGJ1dCBpZgogICAgZ2l2ZW4gc2hvdWxkIG5vdCBjb250
+YWluIHNwYWNlcy4gIFVzZWQgb25seSB3aXRoIGEgZmV3IGNvbW1hbmRzLgoKKioq
+IEZBSUxVUkUgPGxvY2F0aW9uPiA8ZXJyb3JfY29kZT4KICAgIFRoaXMgaXMgdGhl
+IGNvdW50ZXJwYXJ0IHRvIFNVQ0NFU1MgYW5kIHVzZWQgdG8gaW5kaWNhdGUgYSBw
+cm9ncmFtCiAgICBmYWlsdXJlLiAgSXQgaXMgdXNlZCBzaW1pbGFyIHRvIElTTy1D
+J3MgRVhJVF9GQUlMVVJFIGJ1dCBhbGxvd3MgdG8KICAgIGNvbnZleSBtb3JlIGlu
+Zm9ybWF0aW9uLCBpbiBwYXJ0aWN1bGFyIGFuIGdwZy1lcnJvciBlcnJvciBjb2Rl
+LgogICAgVGhhdCBudW1lcmljYWwgZXJyb3IgY29kZSBtYXkgb3B0aW9uYWxseSBo
+YXZlIGEgc3VmZml4IG1hZGUgb2YgYW4KICAgIHVuZGVyc2NvcmUgYW5kIGEgc3Ry
+aW5nIHdpdGggYW4gZXJyb3Igc3ltYm9sIGxpa2UgIjE1MTAxMTMyN19FT0YiLgog
+ICAgQSBkYXNoIG1heSBiZSB1c2VkIGluc3RlYWQgb2YgPGxvY2F0aW9uPi4KCioq
+KiBCQURBUk1PUgogICAgVGhlIEFTQ0lJIGFybW9yIGlzIGNvcnJ1cHRlZC4gIE5v
+IGFyZ3VtZW50cyB5ZXQuCgoqKiogREVMRVRFX1BST0JMRU0gPHJlYXNvbl9jb2Rl
+PgogICAgRGVsZXRpbmcgYSBrZXkgZmFpbGVkLiAgUmVhc29uIGNvZGVzIGFyZToK
+ICAgIC0gMSA6OiBObyBzdWNoIGtleQogICAgLSAyIDo6IE11c3QgZGVsZXRlIHNl
+Y3JldCBrZXkgZmlyc3QKICAgIC0gMyA6OiBBbWJpZ2lvdXMgc3BlY2lmaWNhdGlv
+bgogICAgLSA0IDo6IEtleSBpcyBzdG9yZWQgb24gYSBzbWFydGNhcmQuCgoqKiog
+UFJPR1JFU1MgPHdoYXQ+IDxjaGFyPiA8Y3VyPiA8dG90YWw+CiAgICBVc2VkIGJ5
+IHRoZSBwcmltZWdlbiBhbmQgUHVibGljIGtleSBmdW5jdGlvbnMgdG8gaW5kaWNh
+dGUKICAgIHByb2dyZXNzLiAgPGNoYXI+IGlzIHRoZSBjaGFyYWN0ZXIgZGlzcGxh
+eWVkIHdpdGggbm8gLS1zdGF0dXMtZmQKICAgIGVuYWJsZWQsIHdpdGggdGhlIGxp
+bmVmZWVkIHJlcGxhY2VkIGJ5IGFuICdYJy4gIDxjdXI+IGlzIHRoZQogICAgY3Vy
+cmVudCBhbW91bnQgZG9uZSBhbmQgPHRvdGFsPiBpcyBhbW91bnQgdG8gYmUgZG9u
+ZTsgYSA8dG90YWw+IG9mCiAgICAwIGluZGljYXRlcyB0aGF0IHRoZSB0b3RhbCBh
+bW91bnQgaXMgbm90IGtub3duLiBUaGUgY29uZGl0aW9uCiAgICAgIDogICAgICAg
+VE9UQUwgJiYgQ1VSID09IFRPVEFMCiAgICBtYXkgYmUgdXNlZCB0byBkZXRlY3Qg
+dGhlIGVuZCBvZiBhbiBvcGVyYXRpb24uCgogICAgV2VsbCBrbm93biB2YWx1ZXMg
+Zm9yIFdIQVQgYXJlOgoKICAgICAgICAgICAtIHBrX2RzYSAgIDo6IERTQSBrZXkg
+Z2VuZXJhdGlvbgogICAgICAgICAgIC0gcGtfZWxnICAgOjogRWxnYW1hbCBrZXkg
+Z2VuZXJhdGlvbgogICAgICAgICAgIC0gcHJpbWVnZW4gOjogUHJpbWUgZ2VuZXJh
+dGlvbgogICAgICAgICAgIC0gbmVlZF9lbnRyb3B5IDo6IFdhaXRpbmcgZm9yIG5l
+dyBlbnRyb3B5IGluIHRoZSBSTkcKICAgICAgICAgICAtIHRpY2sgOjogR2VuZXJp
+YyB0aWNrIHdpdGhvdXQgYW55IHNwZWNpYWwgbWVhbmluZyAtIHVzZWZ1bAogICAg
+ICAgICAgICAgICAgICAgICBmb3IgbGV0dGluZyBjbGllbnRzIGtub3cgdGhhdCB0
+aGUgc2VydmVyIGlzIHN0aWxsCiAgICAgICAgICAgICAgICAgICAgIHdvcmtpbmcu
+CiAgICAgICAgICAgLSBzdGFydGluZ19hZ2VudCA6OiBBIGdwZy1hZ2VudCB3YXMg
+c3RhcnRlZCBiZWNhdXNlIGl0IGlzIG5vdAogICAgICAgICAgICAgICAgICAgICAg
+ICAgICAgICAgIHJ1bm5pbmcgYXMgYSBkYWVtb24uCiAgICAgICAgICAgLSBsZWFy
+bmNhcmQgOjogU2VuZCBieSB0aGUgYWdlbnQgYW5kIGdwZ3NtIHdoaWxlIGxlYXJp
+bmcKICAgICAgICAgICAgICAgICAgICAgICAgICB0aGUgZGF0YSBvZiBhIHNtYXJ0
+Y2FyZC4KICAgICAgICAgICAtIGNhcmRfYnVzeSA6OiBBIHNtYXJ0Y2FyZCBpcyBz
+dGlsbCB3b3JraW5nCgoqKiogQkFDS1VQX0tFWV9DUkVBVEVEIDxmaW5nZXJwcmlu
+dD4gPGZuYW1lPgogICAgQSBiYWNrdXAgb2YgYSBrZXkgaWRlbnRpZmllZCBieSA8
+ZmluZ2VycHJpbnQ+IGhhcyBiZWVuIHdyaXR0ZSB0bwogICAgdGhlIGZpbGUgPGZu
+YW1lPjsgPGZuYW1lPiBpcyBwZXJjZW50LWVzY2FwZWQuCgoqKiogTU9VTlRQT0lO
+VCA8bmFtZT4KICAgIDxuYW1lPiBpcyBhIHBlcmNlbnQtcGx1cyBlc2NhcGVkIGZp
+bGVuYW1lIGRlc2NyaWJpbmcgdGhlCiAgICBtb3VudHBvaW50IGZvciB0aGUgY3Vy
+cmVudCBvcGVyYXRpb24gKGUuZy4gdXNlZCBieSAiZzEzIC0tbW91bnQiKS4KICAg
+IFRoaXMgbWF5IGVpdGhlciBiZSB0aGUgc3BlY2lmaWVkIG1vdW50cG9pbnQgb3Ig
+b25lIHJhbmRvbWx5CiAgICBjaG9vc2VuIGJ5IGcxMy4KCioqKiBQSU5FTlRSWV9M
+QVVOQ0hFRCA8cGlkPgogICAgVGhpcyBzdGF0dXMgbGluZSBpcyBlbWl0dGVkIGJ5
+IGdwZyB0byBub3RpZnkgYSBjbGllbnQgdGhhdCBhCiAgICBQaW5lbnRyeSBoYXMg
+YmVlbiBsYXVuY2hlZC4gIDxwaWQ+IGlzIHRoZSBQSUQgb2YgdGhlIFBpbmVudHJ5
+LiAgSXQKICAgIG1heSBiZSB1c2VkIHRvIGRpc3BsYXkgYSBoaW50IHRvIHRoZSB1
+c2VyIGJ1dCBjYW4ndCBiZSB1c2VkIHRvCiAgICBzeW5jaHJvbml6ZSB3aXRoIFBp
+bmVudHJ5LiAgTm90ZSB0aGF0IHRoZXJlIGlzIGFsc28gYW4gQXNzdWFuCiAgICBp
+bnF1aXJ5IGxpbmUgd2l0aCB0aGUgc2FtZSBuYW1lIHVzZWQgaW50ZXJuYWxseSBv
+ciwgaWYgZW5hYmxlZCwKICAgIHNlbmQgdG8gdGhlIGNsaWVudCBpbnN0ZWFkIG9m
+IHRoaXMgc3RhdHVzIGxpbmUuICBTdWNoIGFuIGlucXVpcnkKICAgIG1heSBiZSB1
+c2VkIHRvIHN5bmMgd2l0aCBQaW5lbnRyeQoKKiogT2Jzb2xldGUgc3RhdHVzIGNv
+ZGVzCioqKiBTSUdFWFBJUkVECiAgICBSZW1vdmVkIG9uIDIwMTEtMDItMDQuICBU
+aGlzIGlzIGRlcHJlY2F0ZWQgaW4gZmF2b3Igb2YgS0VZRVhQSVJFRC4KKioqIFJT
+QV9PUl9JREVBCiAgICBPYnNvbGV0ZS4gIFRoaXMgc3RhdHVzIG1lc3NhZ2UgdXNl
+ZCB0byBiZSBlbWl0dGVkIGZvciByZXF1ZXN0cyB0bwogICAgdXNlIHRoZSBJREVB
+IG9yIFJTQSBhbGdvcml0aG1zLiAgSXQgaGFzIGJlZW4gZHJvcHBlZCBmcm9tIEdu
+dVBHCiAgICAyLjEgYWZ0ZXIgdGhlIHJlc3BlY3RpdmUgcGF0ZW50cyBleHBpcmVk
+LgoqKiogU0hNX0lORk8sIFNITV9HRVQsIFNITV9HRVRfQk9PTCwgU0hNX0dFVF9I
+SURERU4KICAgIFRoZXNlIHdlcmUgdXNlZCBmb3IgdGhlIGFuY2llbnQgc2hhcmVk
+IG1lbW9yeSBiYXNlZCBjby1wcm9jZXNzaW5nLgoqKiogQkVHSU5fU1RSRUFNLCBF
+TkRfU1RSRUFNCiAgICBVc2VkIHRvIGlzc3VlZCBieSB0aGUgZXhwZXJpbWVudGFs
+IHBpcGVtb2RlLgoKCiogRm9ybWF0IG9mIHRoZSAtLWF0dHJpYnV0ZS1mZCBvdXRw
+dXQKCiAgV2hlbiAtLWF0dHJpYnV0ZS1mZCBpcyBzZXQsIGR1cmluZyBrZXkgbGlz
+dGluZ3MgKC0tbGlzdC1rZXlzLAogIC0tbGlzdC1zZWNyZXQta2V5cykgR251UEcg
+ZHVtcHMgZWFjaCBhdHRyaWJ1dGUgcGFja2V0IHRvIHRoZSBmaWxlCiAgZGVzY3Jp
+cHRvciBzcGVjaWZpZWQuICAtLWF0dHJpYnV0ZS1mZCBpcyBpbnRlbmRlZCBmb3Ig
+dXNlIHdpdGgKICAtLXN0YXR1cy1mZCBhcyBwYXJ0IG9mIHRoZSByZXF1aXJlZCBp
+bmZvcm1hdGlvbiBpcyBjYXJyaWVkIG9uIHRoZQogIEFUVFJJQlVURSBzdGF0dXMg
+dGFnIChzZWUgYWJvdmUpLgoKICBUaGUgY29udGVudHMgb2YgdGhlIGF0dHJpYnV0
+ZSBkYXRhIGlzIHNwZWNpZmllZCBieSBSRkMgNDg4MC4gIEZvcgogIGNvbnZlbmll
+bmNlLCBoZXJlIGlzIHRoZSBQaG90byBJRCBmb3JtYXQsIGFzIGl0IGlzIGN1cnJl
+bnRseSB0aGUKICBvbmx5IGF0dHJpYnV0ZSBkZWZpbmVkOgoKICAtIEJ5dGUgMC0x
+IDo6IFRoZSBsZW5ndGggb2YgdGhlIGltYWdlIGhlYWRlci4gIER1ZSB0byBhIGhp
+c3RvcmljYWwKICAgICAgICAgICAgICAgIGFjY2lkZW50IChpLmUuIG9vcHMhKSBi
+YWNrIGluIHRoZSBOQUkgUEdQIGRheXMsIHRoaXMKICAgICAgICAgICAgICAgIGlz
+IGEgbGl0dGxlLWVuZGlhbiBudW1iZXIuICBDdXJyZW50bHkgMTYgKDB4MTAgMHgw
+MCkuCgogIC0gQnl0ZSAyIDo6IFRoZSBpbWFnZSBoZWFkZXIgdmVyc2lvbi4gIEN1
+cnJlbnRseSAweDAxLgoKICAtIEJ5dGUgMyA6OiBFbmNvZGluZyBmb3JtYXQuICAw
+eDAxID09IEpQRUcuCgogIC0gQnl0ZSA0LTE1IDo6IFJlc2VydmVkLCBhbmQgY3Vy
+cmVudGx5IHVudXNlZC4KCiAgQWxsIG90aGVyIGRhdGEgYWZ0ZXIgdGhpcyBoZWFk
+ZXIgaXMgcmF3IGltYWdlIChKUEVHKSBkYXRhLgoKCiogVW5hdHRlbmRlZCBrZXkg
+Z2VuZXJhdGlvbgoKICAgUGxlYXNlIHNlZSB0aGUgR251UEcgbWFudWFsIGZvciBh
+IGRlc2NyaXB0aW9uLgoKCiogTGF5b3V0IG9mIHRoZSBUcnVzdERCCgogIFRoZSBU
+cnVzdERCIGlzIGJ1aWx0IGZyb20gZml4ZWQgbGVuZ3RoIHJlY29yZHMsIHdoZXJl
+IHRoZSBmaXJzdCBieXRlCiAgZGVzY3JpYmVzIHRoZSByZWNvcmQgdHlwZS4gIEFs
+bCBudW1lcmljIHZhbHVlcyBhcmUgc3RvcmVkIGluIG5ldHdvcmsKICBieXRlIG9y
+ZGVyLiAgVGhlIGxlbmd0aCBvZiBlYWNoIHJlY29yZCBpcyA0MCBieXRlcy4gIFRo
+ZSBmaXJzdAogIHJlY29yZCBvZiB0aGUgREIgaXMgYWx3YXlzIG9mIHR5cGUgMSBh
+bmQgdGhpcyBpcyB0aGUgb25seSByZWNvcmQgb2YKICB0aGlzIHR5cGUuCgogIFRo
+ZSByZWNvcmQgdHlwZXM6IGRpcmVjdG9yeSgyKSwga2V5KDMpLCB1aWQoNCksIHBy
+ZWYoNSksIHNpZ3JlYyg2KSwKICBhbmQgc2hhZG93IGRpcmVjdG9yeSg4KSBhcmUg
+bm90IGFueW1vcmUgdXNlZCBieSB2ZXJzaW9uIDIgb2YgdGhlCiAgVHJ1c3REQi4K
+CioqIFJlY29yZCB0eXBlIDAKCiAgIFVudXNlZCByZWNvcmQgb3IgZGVsZXRlZCwg
+Y2FuIGJlIHJldXNlZCBmb3IgYW55IHB1cnBvc2UuICBTdWNoCiAgIHJlY29yZHMg
+c2hvdWxkIGluIGdlbmVyYWwgbm90IGV4aXN0IGJlY2F1c2UgZGVsZXRlZCByZWNv
+cmRzIGFyZSBvZgogICB0eXBlIDI1NCBhbmQga2VwdCBpbiBhIGxpbmtlZCBsaXN0
+LgoKKiogVmVyc2lvbiBpbmZvIChSRUNUWVBFX1ZFUiwgMSkKCiAgIFZlcnNpb24g
+aW5mb3JtYXRpb24gZm9yIHRoaXMgVHJ1c3REQi4gIFRoaXMgaXMgYWx3YXlzIHRo
+ZSBmaXJzdAogICByZWNvcmQgb2YgdGhlIERCIGFuZCB0aGUgb25seSBvbmUgb2Yg
+dGhpcyB0eXBlLgoKICAgLSAxIHU4IDo6IFJlY29yZCB0eXBlICh2YWx1ZTogMSku
+CiAgIC0gMyBieXRlIDo6IE1hZ2ljIHZhbHVlICgiZ3BnIikKICAgLSAxIHU4IDo6
+IFRydXN0REIgdmVyc2lvbiAodmFsdWU6IDIpLgogICAtIDEgdTggOjogPW1hcmdp
+bmFscz0uIEhvdyBtYW55IG1hcmdpbmFsIHRydXN0ZWQga2V5cyBhcmUgcmVxdWly
+ZWQuCiAgIC0gMSB1OCA6OiA9Y29tcGxldGVzPS4gSG93IG1hbnkgY29tcGxldGVs
+eSB0cnVzdGVkIGtleXMgYXJlCiAgICAgICAgICAgICByZXF1aXJlZC4KICAgLSAx
+IHU4IDo6ID1tYXhfY2VydF9kZXB0aD0uICBIb3cgZGVlcCBpcyB0aGUgV29UIGV2
+YWx1YXRlZC4gIEFsb25nCiAgICAgICAgICAgICB3aXRoID1tYXJnaW5hbHM9IGFu
+ZCA9Y29tcGxldGVzPSwgdGhpcyB2YWx1ZSBpcyB1c2VkIHRvCiAgICAgICAgICAg
+ICBjaGVjayB3aGV0aGVyIHRoZSBjYWNoZWQgdmFsaWRpdHkgdmFsdWUgZnJvbSBh
+IFtGSVhNRQogICAgICAgICAgICAgZGlyXSByZWNvcmQgY2FuIGJlIHVzZWQuCiAg
+IC0gMSB1OCA6OiA9dHJ1c3RfbW9kZWw9CiAgIC0gMSB1OCA6OiA9bWluX2NlcnRf
+bGV2ZWw9CiAgIC0gMiBieXRlIDo6IE5vdCB1c2VkCiAgIC0gMSB1MzIgOjogPWNy
+ZWF0ZWQ9LiBUaW1lc3RhbXAgb2YgdHJ1c3RkYiBjcmVhdGlvbi4KICAgLSAxIHUz
+MiA6OiA9bmV4dGNoZWNrPS4gVGltZXN0YW1wIG9mIGxhc3QgbW9kaWZpY2F0aW9u
+IHdoaWNoIG1heQogICAgICAgICAgICAgIGFmZmVjdCB0aGUgdmFsaWRpdHkgb2Yg
+a2V5cyBpbiB0aGUgdHJ1c3RkYi4gIFRoaXMgdmFsdWUKICAgICAgICAgICAgICBp
+cyBjaGVja2VkIGFnYWluc3QgdGhlIHZhbGlkaXR5IHRpbWVzdGFtcCBpbiB0aGUg
+ZGlyCiAgICAgICAgICAgICAgcmVjb3Jkcy4KICAgLSAxIHUzMiA6OiA9cmVzZXJ2
+ZWQ9LiAgTm90IHVzZWQuCiAgIC0gMSB1MzIgOjogPXJlc2VydmVkMj0uIE5vdCB1
+c2VkLgogICAtIDEgdTMyIDo6ID1maXJzdGZyZWU9LiBOdW1iZXIgb2YgdGhlIHJl
+Y29yZCB3aXRoIHRoZSBoZWFkIHJlY29yZAogICAgICAgICAgICAgIG9mIHRoZSBS
+RUNUWVBFX0ZSRUUgbGlua2VkIGxpc3QuCiAgIC0gMSB1MzIgOjogPXJlc2VydmVk
+Mz0uIE5vdCB1c2VkLgogICAtIDEgdTMyIDo6ID10cnVzdGhhc2h0Ymw9LiBSZWNv
+cmQgbnVtYmVyIG9mIHRoZSB0cnVzdGhhc2h0YWJsZS4KCgoqKiBIYXNoIHRhYmxl
+IChSRUNUWVBFX0hUQkwsIDEwKQoKICAgRHVlIHRvIHRoZSBmYWN0IHRoYXQgd2Ug
+dXNlIGZpbmdlcnByaW50cyB0byBsb29rdXAga2V5cywgd2UgY2FuCiAgIGltcGxl
+bWVudCBxdWljayBhY2Nlc3MgYnkgc29tZSBzaW1wbGUgaGFzaCBtZXRob2RzLCBh
+bmQgYXZvaWQgdGhlCiAgIG92ZXJoZWFkIG9mIGdkYm0uICBBIHByb3BlcnR5IG9m
+IGZpbmdlcnByaW50cyBpcyB0aGF0IHRoZXkgY2FuIGJlCiAgIHVzZWQgZGlyZWN0
+bHkgYXMgaGFzaCB2YWx1ZXMuICBXaGF0IHdlIHVzZSBpcyBhIGR5bmFtaWMgbXVs
+dGlsZXZlbAogICBhcmNoaXRlY3R1cmUsIHdoaWNoIGNvbWJpbmVzIGhhc2ggdGFi
+bGVzLCByZWNvcmQgbGlzdHMsIGFuZCBsaW5rZWQKICAgbGlzdHMuCgogICBUaGlz
+IHJlY29yZCBpcyBhIGhhc2ggdGFibGUgb2YgMjU2IGVudHJpZXMgd2l0aCB0aGUg
+cHJvcGVydHkgdGhhdAogICBhbGwgdGhlc2UgcmVjb3JkcyBhcmUgc3RvcmVkIGNv
+bnNlY3V0aXZlbHkgdG8gbWFrZSBvbmUgYmlnCiAgIHRhYmxlLiBUaGUgaGFzaCB2
+YWx1ZSBpcyBzaW1wbGUgdGhlIDFzdCwgMm5kLCAuLi4gYnl0ZSBvZiB0aGUKICAg
+ZmluZ2VycHJpbnQgKGRlcGVuZGluZyBvbiB0aGUgaW5kaXJlY3Rpb24gbGV2ZWwp
+LgoKICAgLSAxIHU4IDo6IFJlY29yZCB0eXBlICh2YWx1ZTogMTApLgogICAtIDEg
+dTggOjogUmVzZXJ2ZWQKICAgLSBuIHUzMiA6OiA9cmVjbnVtPS4gIEEgdGFibGUg
+d2l0aCB0aGUgaGFzaCB0YWJsZSBpdGVtcyBmaXR0aW5nIGludG8KICAgICAgICAg
+ICAgICB0aGlzIHJlY29yZC4gID1uPSBkZXBlbmRzIG9uIHRoZSByZWNvcmQgbGVu
+Z3RoOgogICAgICAgICAgICAgICRuPShyZWNsZW4tMikvNCQgd2hpY2ggeWllbGRz
+IDkgZm9yIG91cmUgY3VycmVudCByZWNvcmQKICAgICAgICAgICAgICBsZW5ndGgg
+b2YgNDAgYnl0ZXMuCgogICBUaGUgdG90YWwgbnVtYmVyIG9mIGhhc2ggdGFibGUg
+cmVjb3JkcyB0byBmb3JtIHRoZSB0YWJsZSBpczoKICAgJG09KDI1NituLTEpL24k
+LiAgVGhpcyBpcyAyOSBmb3Igb3VyIHJlY29yZCBsZW5ndGggb2YgNDAuCgogICBU
+byBsb29rIHVwIGEga2V5IHdlIHVzZSB0aGUgZmlyc3QgYnl0ZSBvZiB0aGUgZmlu
+Z2VycHJpbnQgdG8gZ2V0CiAgIHRoZSByZWNudW0gZnJvbSB0aGlzIGhhc2ggdGFi
+bGUgYW5kIHRoZW4gbG9vayB1cCB0aGUgYWRkcmVzc2VkCiAgIHJlY29yZDoKCiAg
+IC0gSWYgdGhhdCByZWNvcmQgaXMgYW5vdGhlciBoYXNoIHRhYmxlLCB3ZSB1c2Ug
+Mm5kIGJ5dGUgdG8gaW5kZXgKICAgICB0aGF0IGhhc2ggdGFibGUgYW5kIHNvIG9u
+OwogICAtIGlmIHRoYXQgcmVjb3JkIGlzIGEgaGFzaCBsaXN0LCB3ZSB3YWxrIGFs
+bCBlbnRyaWVzIHVudGlsIHdlIGZpbmQKICAgICBhIG1hdGNoaW5nIG9uZTsgb3IK
+ICAgLSBpZiB0aGF0IHJlY29yZCBpcyBhIGtleSByZWNvcmQsIHdlIGNvbXBhcmUg
+dGhlIGZpbmdlcnByaW50IHRvCiAgICAgZGVjaWRlIHdoZXRoZXIgaXQgaXMgdGhl
+IHJlcXVlc3RlZCBrZXk7CgoKKiogSGFzaCBsaXN0IChSRUNUWVBFX0hMU1QsIDEx
+KQoKICAgU2VlIGhhc2ggdGFibGUgYWJvdmUgb24gaG93IGl0IGlzIHVzZWQuICBJ
+dCBtYXkgYWxzbyBiZSB1c2VkIGZvcgogICBvdGhlciBwdXJwb3Nlcy4KCiAgIC0g
+MSB1OCA6OiBSZWNvcmQgdHlwZSAodmFsdWU6IDExKS4KICAgLSAxIHU4IDo6IFJl
+c2VydmVkLgogICAtIDEgdTMyIDo6ID1uZXh0PS4gIFJlY29yZCBudW1iZXIgb2Yg
+dGhlIG5leHQgaGFzaCBsaXN0IHJlY29yZCBvciAwCiAgICAgICAgICAgICAgaWYg
+bm9uZS4KICAgLSBuIHUzMiA6OiA9cm51bT0uICBBcnJheSB3aXRoIHJlY29yZCBu
+dW1iZXJzIHRvIHZhbHVlcy4gIFdpdGgKICAgICAgICAgICAgICAkbj0ocmVjbGVu
+LTUpLzUkIGFuZCBvdXIgcmVjb3JkIGxlbmd0aCBvZiA0MCwgbiBpcyA3LgoKKiog
+VHJ1c3QgcmVjb3JkIChSRUNUWVBFX1RSVVNULCAxMikKCiAgIC0gMSB1OCA6OiBS
+ZWNvcmQgdHlwZSAodmFsdWU6IDEyKS4KICAgLSAxIHU4IDo6IFJlc2VydmVkLgog
+ICAtIDIwIGJ5dGUgOjogPWZpbmdlcnByaW50PS4KICAgLSAxIHU4IDo6ID1vd25l
+cnRydXN0PS4KICAgLSAxIHU4IDo6ID1kZXB0aD0uCiAgIC0gMSB1OCA6OiA9bWlu
+X293bmVydHJ1c3Q9LgogICAtIDEgYnl0ZSA6OiBOb3QgdXNlZC4KICAgLSAxIHUz
+MiA6OiA9dmFsaWRsaXN0PS4KICAgLSAxMCBieXRlIDo6IE5vdCB1c2VkLgoKKiog
+VmFsaWRpdHkgcmVjb3JkIChSRUNUWVBFX1ZBTElELCAxMykKCiAgIC0gMSB1OCA6
+OiBSZWNvcmQgdHlwZSAodmFsdWU6IDEzKS4KICAgLSAxIHU4IDo6IFJlc2VydmVk
+LgogICAtIDIwIGJ5dGUgOjogPW5hbWVoYXNoPS4KICAgLSAxIHU4IDo6ID12YWxp
+ZGl0eT0KICAgLSAxIHUzMiA6OiA9bmV4dD0uCiAgIC0gMSB1OCA6OiA9ZnVsbF9j
+b3VudD0uCiAgIC0gMSB1OCA6OiA9bWFyZ2luYWxfY291bnQ9LgogICAtIDExIGJ5
+dGUgOjogTm90IHVzZWQuCgoqKiBGcmVlIHJlY29yZCAoUkVDVFlQRV9GUkVFLCAy
+NTQpCgogICBBbGwgdGhlc2UgcmVjb3JkcyBmb3JtIGEgbGlua2VkIGxpc3Qgb2Yg
+dW51c2VkIHJlY29yZHMgaW4gdGhlIFRydXN0REIuCgogICAtIDEgdTggOjogUmVj
+b3JkIHR5cGUgKHZhbHVlOiAyNTQpCiAgIC0gMSB1OCA6OiBSZXNlcnZlZC4KICAg
+LSAxIHUzMiA6OiA9bmV4dD0uICBSZWNvcmQgbnVtYmVyIG9mIHRoZSBuZXh0IHJj
+b3JkIG9mIHRoaXMgdHlwZS4KICAgICAgICAgICAgICBUaGUgcmVjb3JkIG51bWJl
+ciB0byB0aGUgaGVhZCBvZiB0aGlzIGxpbmtlZCBsaXN0IGlzCiAgICAgICAgICAg
+ICAgc3RvcmVkIGluIHRoZSB2ZXJzaW9uIGluZm8gcmVjb3JkLgoKCiogR05VIGV4
+dGVuc2lvbnMgdG8gdGhlIFMySyBhbGdvcml0aG0KCiAgMSBvY3RldCAgLSBTMksg
+VXNhZ2U6IGVpdGhlciAyNTQgb3IgMjU1LgogIDEgb2N0ZXQgIC0gUzJLIENpcGhl
+ciBBbGdvOiAwCiAgMSBvY3RldCAgLSBTMksgU3BlY2lmaWVyOiAxMDEKICAzIG9j
+dGV0cyAtICJHTlUiCiAgMSBvY3RldCAgLSBHTlUgUzJLIEV4dGVuc2lvbiBOdW1i
+ZXIuCgogIElmIHN1Y2ggYSBHTlUgZXh0ZW5zaW9uIGlzIHVzZWQgbmVpdGhlciBh
+biBJViBub3IgYW55IGtpbmQgb2YKICBjaGVja3N1bSBpcyB1c2VkLiAgVGhlIGRl
+ZmluZWQgR05VIFMySyBFeHRlbnNpb24gTnVtYmVycyBhcmU6CgogIC0gMSA6OiBE
+byBub3Qgc3RvcmUgdGhlIHNlY3JldCBwYXJ0IGF0IGFsbC4gIE5vIHNwZWNpZmlj
+IGRhdGEKICAgICAgICAgZm9sbG93cy4KCiAgLSAyIDo6IEEgc3R1YiB0byBhY2Nl
+c3Mgc21hcnRjYXJkcy4gIFRoaXMgZGF0YSBmb2xsb3dzOgogICAgICAgICAtIE9u
+ZSBvY3RldCB3aXRoIHRoZSBsZW5ndGggb2YgdGhlIGZvbGxvd2luZyBzZXJpYWwg
+bnVtYmVyLgogICAgICAgICAtIFRoZSBzZXJpYWwgbnVtYmVyLiBSZWdhcmRsZXNz
+IG9mIHdoYXQgdGhlIGxlbmd0aCBvY3RldAogICAgICAgICAgIGluZGljYXRlcyBu
+byBtb3JlIHRoYW4gMTYgb2N0ZXRzIGFyZSBzdG9yZWQuCgogIE5vdGUgdGhhdCBn
+cGcgc3RvcmVzIHRoZSBHTlUgUzJLIEV4dGVuc2lvbiBOdW1iZXIgaW50ZXJuYWxs
+eSBhcyBhbgogIFMySyBTcGVjaWZpZXIgd2l0aCBhbiBvZmZzZXQgb2YgMTAwMC4K
+CgoqIEtleXNlcnZlciBoZWxwZXIgbWVzc2FnZSBmb3JtYXQKCiAgVGhlIGtleXNl
+cnZlciBtYXkgYmUgY29udGFjdGVkIGJ5IGEgVW5peCBEb21haW4gc29ja2V0IG9y
+IHZpYSBUQ1AuCgogIFRoZSBmb3JtYXQgb2YgYSByZXF1ZXN0IGlzOgojK2JlZ2lu
+X2V4YW1wbGUKICBjb21tYW5kLXRhZwogICJDb250ZW50LWxlbmd0aDoiIGRpZ2l0
+cwogIENSTEYKIytlbmRfZXhhbXBsZQoKICBXaGVyZSBjb21tYW5kLXRhZyBpcwoK
+IytiZWdpbl9leGFtcGxlCiAgTk9PUAogIEdFVCA8dXNlci1uYW1lPgogIFBVVAog
+IERFTEVURSA8dXNlci1uYW1lPgojK2VuZF9leGFtcGxlCgpUaGUgZm9ybWF0IG9m
+IGEgcmVzcG9uc2UgaXM6CgojK2JlZ2luX2V4YW1wbGUKICAiR05VUEcvMS4wIiBz
+dGF0dXMtY29kZSBzdGF0dXMtdGV4dAogICJDb250ZW50LWxlbmd0aDoiIGRpZ2l0
+cwogIENSTEYKIytlbmRfZXhhbXBsZQpmb2xsb3dlZCBieSA8ZGlnaXRzPiBieXRl
+cyBvZiBkYXRhCgpTdGF0dXMgY29kZXMgYXJlOgoKICAtIDF4eCA6OiBJbmZvcm1h
+dGlvbmFsIC0gUmVxdWVzdCByZWNlaXZlZCwgY29udGludWluZyBwcm9jZXNzCgog
+IC0gMnh4IDo6IFN1Y2Nlc3MgLSBUaGUgYWN0aW9uIHdhcyBzdWNjZXNzZnVsbHkg
+cmVjZWl2ZWQsIHVuZGVyc3Rvb2QsCiAgICAgICAgICAgYW5kIGFjY2VwdGVkCgog
+IC0gNHh4IDo6IENsaWVudCBFcnJvciAtIFRoZSByZXF1ZXN0IGNvbnRhaW5zIGJh
+ZCBzeW50YXggb3IgY2Fubm90IGJlCiAgICAgICAgICAgZnVsZmlsbGVkCgogIC0g
+NXh4IDo6IFNlcnZlciBFcnJvciAtIFRoZSBzZXJ2ZXIgZmFpbGVkIHRvIGZ1bGZp
+bGwgYW4gYXBwYXJlbnRseQogICAgICAgICAgIHZhbGlkIHJlcXVlc3QKCgoqIE9i
+amVjdCBpZGVudGlmaWVycwoKICBPSURzIGJlbG93IHRoZSBHbnVQRyBhcmM6Cgoj
+K2JlZ2luX2V4YW1wbGUKICAxLjMuNi4xLjQuMS4xMTU5MS4yICAgICAgICAgIEdu
+dVBHCiAgMS4zLjYuMS40LjEuMTE1OTEuMi4xICAgICAgICAgIG5vdGF0aW9uCiAg
+MS4zLjYuMS40LjEuMTE1OTEuMi4xLjEgICAgICAgICAgcGthQWRkcmVzcwogIDEu
+My42LjEuNC4xLjExNTkxLjIuMiAgICAgICAgICBYLjUwOSBleHRlbnNpb25zCiAg
+MS4zLjYuMS40LjEuMTE1OTEuMi4yLjEgICAgICAgICAgc3RhbmRhbG9uZUNlcnRp
+ZmljYXRlCiAgMS4zLjYuMS40LjEuMTE1OTEuMi4yLjIgICAgICAgICAgd2VsbEtu
+b3duUHJpdmF0ZUtleQogIDEuMy42LjEuNC4xLjExNTkxLjIuMTIyNDI5NzMgICBp
+bnZhbGlkIGVuY29kZWQgT0lECiMrZW5kX2V4YW1wbGUKCgoKKiBNaXNjZWxsYW5l
+b3VzIG5vdGVzCgoqKiB2MyBmaW5nZXJwcmludHMKICAgRm9yIHBhY2tldCB2ZXJz
+aW9uIDMgd2UgY2FsY3VsYXRlIHRoZSBrZXlpZHMgdGhpcyB3YXk6CiAgICAtIFJT
+QSA6OiBMb3cgNjQgYml0cyBvZiBuCiAgICAtIEVMR0FNQUwgOjogQnVpbGQgYSB2
+MyBwdWJrZXkgcGFja2V0ICh3aXRoIENUQiAweDk5KSBhbmQKICAgICAgICAgICAg
+ICAgICBjYWxjdWxhdGUgYSBSTUQxNjAgaGFzaCB2YWx1ZSBmcm9tIGl0LiBUaGlz
+IGlzIHVzZWQKICAgICAgICAgICAgICAgICBhcyB0aGUgZmluZ2VycHJpbnQgYW5k
+IHRoZSBsb3cgNjQgYml0cyBhcmUgdGhlIGtleWlkLgoKKiogU2ltcGxpZmllZCBy
+ZXZvY2F0aW9uIGNlcnRpZmljYXRlcwogIFJldm9jYXRpb24gY2VydGlmaWNhdGVz
+IGNvbnNpc3Qgb25seSBvZiB0aGUgc2lnbmF0dXJlIHBhY2tldDsKICAiLS1pbXBv
+cnQiIGtub3dzIGhvdyB0byBoYW5kbGUgdGhpcy4gIFRoZSByYXRpb25hbGUgYmVo
+aW5kIGl0IGlzIHRvCiAga2VlcCB0aGVtIHNtYWxsLgoKKiogRG9jdW1lbnRhdGlv
+biBvbiBIS1AgKHRoZSBodHRwIGtleXNlcnZlciBwcm90b2NvbCk6CgogICBBIG1p
+bmltYWxpc3RpYyBIVFRQIHNlcnZlciBvbiBwb3J0IDExMzcxIHJlY29nbml6ZXMg
+YSBHRVQgZm9yCiAgIC9wa3MvbG9va3VwLiAgVGhlIHN0YW5kYXJkIGh0dHAgVVJM
+IGVuY29kZWQgcXVlcnkgcGFyYW1ldGVycyBhcmUKICAgdGhpcyAoYWx3YXlzIGtl
+eT12YWx1ZSk6CgogICAtIG9wPWluZGV4IChsaWtlIHBncCAta3YpLCBvcD12aW5k
+ZXggKGxpa2UgcGdwIC1rdnYpIGFuZCBvcD1nZXQgKGxpa2UKICAgICBwZ3AgLWt4
+YSkKCiAgIC0gc2VhcmNoPTxzdHJpbmdsaXN0Pi4gVGhpcyBpcyBhIGxpc3Qgb2Yg
+d29yZHMgdGhhdCBtdXN0IG9jY3VyIGluIHRoZSBrZXkuCiAgICAgVGhlIHdvcmRz
+IGFyZSBkZWxpbWl0ZWQgd2l0aCBzcGFjZSwgcG9pbnRzLCBAIGFuZCBzbyBvbi4g
+VGhlIGRlbGltaXRlcnMKICAgICBhcmUgbm90IHNlYXJjaGVkIGZvciBhbmQgdGhl
+IG9yZGVyIG9mIHRoZSB3b3JkcyBkb2Vzbid0IG1hdHRlciAoYnV0IHNlZQogICAg
+IG5leHQgb3B0aW9uKS4KCiAgIC0gZXhhY3Q9b24uIFRoaXMgc3dpdGNoIHRlbGxz
+IHRoZSBoa3Agc2VydmVyIHRvIG9ubHkgcmVwb3J0IGV4YWN0IG1hdGNoaW5nCiAg
+ICAga2V5cyBiYWNrLiBJbiB0aGlzIGNhc2UgdGhlIG9yZGVyIGFuZCB0aGUgImRl
+bGltaXRlcnMiIGFyZSBpbXBvcnRhbnQuCgogICAtIGZpbmdlcnByaW50PW9uLiBB
+bHNvIHJlcG9ydHMgdGhlIGZpbmdlcnByaW50cyB3aGVuIHVzZWQgd2l0aCAnaW5k
+ZXgnIG9yCiAgICAgJ3ZpbmRleCcKCiAgIFRoZSBrZXlzZXJ2ZXIgYWxzbyByZWNv
+Z25pemVzIGh0dHAtUE9TVHMgdG8gL3Brcy9hZGQuIFVzZSB0aGlzIHRvIHVwbG9h
+ZAogICBrZXlzLgoKCiAgIEEgYmV0dGVyIHdheSB0byBkbyB0aGlzIHdvdWxkIGJl
+IGEgcmVxdWVzdCBsaWtlOgoKICAgICAgL3Brcy9sb29rdXAvPGdudXBnX2Zvcm1h
+dGllcnRlX3VzZXJfaWQ+P29wPTxvcGVyYXRpb24+CgogICBUaGlzIGNhbiBiZSBp
+bXBsZW1lbnRlZCB1c2luZyBIdXJkJ3MgdHJhbnNsYXRvciBtZWNoYW5pc20uCiAg
+IEhvd2V2ZXIsIEkgdGhpbmsgdGhlIHdob2xlIGtleSBzZXJ2ZXIgc3R1ZmYgaGFz
+IHRvIGJlIHJlLXRob3VnaHQ7CiAgIEkgaGF2ZSBzb21lIGlkZWFzIGFuZCBwcm9i
+YWJseSBjcmVhdGUgYSB3aGl0ZSBwYXBlci4KKiogQWxnb3JpdGhtIG5hbWVzIGZv
+ciB0aGUgImtleWdlbi5hbGdvIiBwcm9tcHQKCiAgV2hlbiB1c2luZyBhIC0tY29t
+bWFuZC1mZCBjb250cm9sbGVkIGtleSBnZW5lcmF0aW9uIG9yICJhZGRrZXkiCiAg
+dGhlcmUgaXMgd2F5IHRvIGtub3cgdGhlIG51bWJlciB0byBlbnRlciBvbiB0aGUg
+ImtleWdlbi5hbGdvIgogIHByb21wdC4gIFRoZSBkaXNwbGF5ZWQgbnVtYmVycyBh
+cmUgZm9yIGh1bWFuIHJlY2VwdGlvbiBhbmQgbWF5CiAgY2hhbmdlIHdpdGggcmVs
+ZWFzZXMuICBUbyBwcm92aWRlIGEgc3RhYmxlIHdheSB0byBlbnRlciBhIGRlc2ly
+ZWQKICBhbGdvcml0aG0gY2hvaWNlIHRoZSBwcm9tcHQgYWxzbyBhY2NlcHRzIHBy
+ZWRlZmluZWQgbmFtZXMgZm9yIHRoZQogIGFsZ29yaXRobXMsIHdoaWNoIHdpbGwg
+bm90IGNoYW5nZS4KCiAgIHwgTmFtZSAgICB8IE5vIHwgRGVzY3JpcHRpb24gICAg
+ICAgICAgICAgICAgICAgICB8CiAgIHwtLS0tLS0tLS0rLS0tLSstLS0tLS0tLS0t
+LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18CiAgIHwgcnNhK3JzYSB8ICAxIHwgUlNB
+IGFuZCBSU0EgKGRlZmF1bHQpICAgICAgICAgICB8CiAgIHwgZHNhK2VsZyB8ICAy
+IHwgRFNBIGFuZCBFbGdhbWFsICAgICAgICAgICAgICAgICB8CiAgIHwgZHNhICAg
+ICB8ICAzIHwgRFNBIChzaWduIG9ubHkpICAgICAgICAgICAgICAgICB8CiAgIHwg
+cnNhL3MgICB8ICA0IHwgUlNBIChzaWduIG9ubHkpICAgICAgICAgICAgICAgICB8
+CiAgIHwgZWxnICAgICB8ICA1IHwgRWxnYW1hbCAoZW5jcnlwdCBvbmx5KSAgICAg
+ICAgICB8CiAgIHwgcnNhL2UgICB8ICA2IHwgUlNBIChlbmNyeXB0IG9ubHkpICAg
+ICAgICAgICAgICB8CiAgIHwgZHNhLyogICB8ICA3IHwgRFNBIChzZXQgeW91ciBv
+d24gY2FwYWJpbGl0aWVzKSB8CiAgIHwgcnNhLyogICB8ICA4IHwgUlNBIChzZXQg
+eW91ciBvd24gY2FwYWJpbGl0aWVzKSB8CiAgIHwgZWNjK2VjYyB8ICA5IHwgRUND
+IGFuZCBFQ0MgICAgICAgICAgICAgICAgICAgICB8CiAgIHwgZWNjL3MgICB8IDEw
+IHwgRUNDIChzaWduIG9ubHkpICAgICAgICAgICAgICAgICB8CiAgIHwgZWNjLyog
+ICB8IDExIHwgRUNDIChzZXQgeW91ciBvd24gY2FwYWJpbGl0aWVzKSB8CiAgIHwg
+ZWNjL2UgICB8IDEyIHwgRUNDIChlbmNyeXB0IG9ubHkpICAgICAgICAgICAgICB8
+CiAgIHwga2V5Z3JpcCB8IDEzIHwgRXhpc3Rpbmcga2V5ICAgICAgICAgICAgICAg
+ICAgICB8CgogICBJZiBvbmUgb2YgdGhlICJmb28vKiIgbmFtZXMgYXJlIHVzZWQg
+YSAia2V5Z2VuLmZsYWdzIiBwcm9tcHQgbmVlZHMKICAgdG8gYmUgYW5zd2VyZWQg
+YXMgd2VsbC4gIEluc3RlYWQgb2YgdG9nZ2xpbmcgdGhlIHByZWRlZmluZWQgZmxh
+Z3MsCiAgIGl0IGlzIGFsc28gcG9zc2libGUgdG8gc2V0IHRoZW0gZGlyZWN0OiBV
+c2UgYSAiPSIgY2hhcmFjdGVyCiAgIGRpcmVjdGx5IGZvbGxvd2VkIGJ5IGEgY29t
+aW5hdGlvbiBvZiAiYSIgKGZvciBhdXRoZW50aWNhdGlvbiksICJzIgogICAoZm9y
+IHNpZ25pbmcpLCBvciAiYyIgKGZvciBjZXJ0aWZpY2F0aW9uKS4KQGMgQ29weXJp
+Z2h0IChDKSAxOTk4LCAxOTk5LCAyMDAwLCAyMDAxLCAyMDAyLCAyMDAzLCAyMDA0
+LCAyMDA1LCAyMDA2LCAyMDA3LApAYyAgICAgICAgICAgICAgIDIwMDgsIDIwMDks
+IDIwMTAgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBJbmMuCkBjIFRoaXMgaXMg
+cGFydCBvZiB0aGUgR251UEcgbWFudWFsLgpAYyBGb3IgY29weWluZyBjb25kaXRp
+b25zLCBzZWUgdGhlIGZpbGUgZ251cGcudGV4aS4KCkBpbmNsdWRlIGRlZnMuaW5j
+CgpAbm9kZSBJbnZva2luZyBHUEcKQGNoYXB0ZXIgSW52b2tpbmcgR1BHCkBjaW5k
+ZXggR1BHIGNvbW1hbmQgb3B0aW9ucwpAY2luZGV4IGNvbW1hbmQgb3B0aW9ucwpA
+Y2luZGV4IG9wdGlvbnMsIEdQRyBjb21tYW5kCgpAbWFjcm8gZ3BnbmFtZQpncGcy
+CkBlbmQgbWFjcm8KQG1hbnBhZ2UgZ3BnMi4xCkBpZnNldCBtYW52ZXJiCi5CIGdw
+ZzIKXC0gT3BlblBHUCBlbmNyeXB0aW9uIGFuZCBzaWduaW5nIHRvb2wKQGVuZCBp
+ZnNldAoKQG1hbnNlY3Qgc3lub3BzaXMKQGlmc2V0IG1hbnZlcmIKLkIgIGdwZzIK
+LlJCIFsgXC1cLWhvbWVkaXIKLklSIGRpciBdCi5SQiBbIFwtXC1vcHRpb25zCi5J
+UiBmaWxlIF0KLlJJIFsgb3B0aW9ucyBdCi5JIGNvbW1hbmQKLlJJIFsgYXJncyBd
+CkBlbmQgaWZzZXQKCgpAbWFuc2VjdCBkZXNjcmlwdGlvbgpAY29tbWFuZHtAZ3Bn
+bmFtZX0gaXMgdGhlIE9wZW5QR1AgcGFydCBvZiB0aGUgR05VIFByaXZhY3kgR3Vh
+cmQgKEdudVBHKS4gSXQKaXMgYSB0b29sIHRvIHByb3ZpZGUgZGlnaXRhbCBlbmNy
+eXB0aW9uIGFuZCBzaWduaW5nIHNlcnZpY2VzIHVzaW5nIHRoZQpPcGVuUEdQIHN0
+YW5kYXJkLiBAY29tbWFuZHtAZ3BnbmFtZX0gZmVhdHVyZXMgY29tcGxldGUga2V5
+IG1hbmFnZW1lbnQgYW5kCmFsbCBiZWxscyBhbmQgd2hpc3RsZXMgeW91IGNhbiBl
+eHBlY3QgZnJvbSBhIGRlY2VudCBPcGVuUEdQCmltcGxlbWVudGF0aW9uLgoKSW4g
+Y29udHJhc3QgdG8gdGhlIHN0YW5kYWxvbmUgY29tbWFuZCBncGcgZnJvbSBHbnVQ
+RyAxLngsIHdoaWNoIGlzCm1pZ2h0IGJlIGJldHRlciBzdWl0ZWQgZm9yIHNlcnZl
+ciBhbmQgZW1iZWRkZWQgcGxhdGZvcm1zLCB0aGUgMi54CnZlcnNpb24gaXMgY29t
+bW9ubHkgaW5zdGFsbGVkIHVuZGVyIHRoZSBuYW1lIEBjb21tYW5ke2dwZzJ9IGFu
+ZAp0YXJnZXRlZCB0byB0aGUgZGVza3RvcCBhcyBpdCByZXF1aXJlcyBzZXZlcmFs
+IG90aGVyIG1vZHVsZXMgdG8gYmUKaW5zdGFsbGVkLgoKQG1hbnBhdXNlClRoZSBv
+bGQgMS54IHZlcnNpb24gd2lsbCBiZSBrZXB0IG1haW50YWluZWQgYW5kIGl0IGlz
+IHBvc3NpYmxlIHRvCmluc3RhbGwgYm90aCB2ZXJzaW9ucyBvbiB0aGUgc2FtZSBz
+eXN0ZW0uICBEb2N1bWVudGF0aW9uIGZvciB0aGUgb2xkCkdudVBHIDEueCBjb21t
+YW5kIGlzIGF2YWlsYWJsZSBhcyBhIG1hbiBwYWdlIGFuZCBhdApAaW5mb3JlZntU
+b3AsR251UEcgMSxncGd9LgoKQHhyZWZ7T3B0aW9uIEluZGV4fSwgZm9yIGFuIGlu
+ZGV4IHRvIEBjb21tYW5ke0BncGduYW1lfSdzIGNvbW1hbmRzIGFuZCBvcHRpb25z
+LgpAbWFuY29udAoKQG1lbnUKKiBHUEcgQ29tbWFuZHM6OiAgICAgICAgICAgIExp
+c3Qgb2YgYWxsIGNvbW1hbmRzLgoqIEdQRyBPcHRpb25zOjogICAgICAgICAgICAg
+TGlzdCBvZiBhbGwgb3B0aW9ucy4KKiBHUEcgQ29uZmlndXJhdGlvbjo6ICAgICAg
+IENvbmZpZ3VyYXRpb24gZmlsZXMuCiogR1BHIEV4YW1wbGVzOjogICAgICAgICAg
+ICBTb21lIHVzYWdlIGV4YW1wbGVzLgoKRGV2ZWxvcGVyIGluZm9ybWF0aW9uOgoq
+IFVuYXR0ZW5kZWQgVXNhZ2Ugb2YgR1BHOjogVXNpbmcgQGNvbW1hbmR7Z3BnfSBm
+cm9tIG90aGVyIHByb2dyYW1zLgpAZW5kIG1lbnUKCkBjICogR1BHIFByb3RvY29s
+OjogICAgICAgIFRoZSBwcm90b2NvbCB0aGUgc2VydmVyIG1vZGUgdXNlcy4KCgpA
+YyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCkBj
+ICoqKioqKioqKioqKioqKiAgICAgICAgICAgICoqKioqKioqKioqKioqKioKQGMg
+KioqKioqKioqKioqKioqICBDT01NQU5EUyAgKioqKioqKioqKioqKioqKgpAYyAq
+KioqKioqKioqKioqKiogICAgICAgICAgICAqKioqKioqKioqKioqKioqCkBjICoq
+KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKQG1hbnNl
+Y3QgY29tbWFuZHMKQG5vZGUgR1BHIENvbW1hbmRzCkBzZWN0aW9uIENvbW1hbmRz
+CgpDb21tYW5kcyBhcmUgbm90IGRpc3Rpbmd1aXNoZWQgZnJvbSBvcHRpb25zIGV4
+Y2VwdCBmb3IgdGhlIGZhY3QgdGhhdApvbmx5IG9uZSBjb21tYW5kIGlzIGFsbG93
+ZWQuCgpAY29tbWFuZHtAZ3BnbmFtZX0gbWF5IGJlIHJ1biB3aXRoIG5vIGNvbW1h
+bmRzLCBpbiB3aGljaCBjYXNlIGl0IHdpbGwKcGVyZm9ybSBhIHJlYXNvbmFibGUg
+YWN0aW9uIGRlcGVuZGluZyBvbiB0aGUgdHlwZSBvZiBmaWxlIGl0IGlzIGdpdmVu
+CmFzIGlucHV0IChhbiBlbmNyeXB0ZWQgbWVzc2FnZSBpcyBkZWNyeXB0ZWQsIGEg
+c2lnbmF0dXJlIGlzIHZlcmlmaWVkLAphIGZpbGUgY29udGFpbmluZyBrZXlzIGlz
+IGxpc3RlZCkuCgpQbGVhc2UgcmVtZW1iZXIgdGhhdCBvcHRpb24gYXMgd2VsbCBh
+cyBjb21tYW5kIHBhcnNpbmcgc3RvcHMgYXMgc29vbiBhcwphIG5vbi1vcHRpb24g
+aXMgZW5jb3VudGVyZWQsIHlvdSBjYW4gZXhwbGljaXRseSBzdG9wIHBhcnNpbmcg
+YnkKdXNpbmcgdGhlIHNwZWNpYWwgb3B0aW9uIEBvcHRpb257LS19LgoKCkBtZW51
+CiogR2VuZXJhbCBHUEcgQ29tbWFuZHM6OiAgICAgICAgQ29tbWFuZHMgbm90IHNw
+ZWNpZmljIHRvIHRoZSBmdW5jdGlvbmFsaXR5LgoqIE9wZXJhdGlvbmFsIEdQRyBD
+b21tYW5kczo6ICAgIENvbW1hbmRzIHRvIHNlbGVjdCB0aGUgdHlwZSBvZiBvcGVy
+YXRpb24uCiogT3BlblBHUCBLZXkgTWFuYWdlbWVudDo6ICAgICAgSG93IHRvIG1h
+bmFnZSB5b3VyIGtleXMuCkBlbmQgbWVudQoKCkBjICoqKioqKioqKioqKioqKioq
+KioqKioqKioqKioqKioqKioqKioqKioqKioKQGMgKioqKioqKioqKiAgR0VORVJB
+TCBDT01NQU5EUyAgKioqKioqKioqKioqKgpAYyAqKioqKioqKioqKioqKioqKioq
+KioqKioqKioqKioqKioqKioqKioqKioqCkBub2RlIEdlbmVyYWwgR1BHIENvbW1h
+bmRzCkBzdWJzZWN0aW9uIENvbW1hbmRzIG5vdCBzcGVjaWZpYyB0byB0aGUgZnVu
+Y3Rpb24KCkB0YWJsZSBAZ251cGd0YWJvcHQKQGl0ZW0gLS12ZXJzaW9uCkBvcGlu
+ZGV4IHZlcnNpb24KUHJpbnQgdGhlIHByb2dyYW0gdmVyc2lvbiBhbmQgbGljZW5z
+aW5nIGluZm9ybWF0aW9uLiAgTm90ZSB0aGF0IHlvdQpjYW5ub3QgYWJicmV2aWF0
+ZSB0aGlzIGNvbW1hbmQuCgpAaXRlbSAtLWhlbHAKQGl0ZW14IC1oCkBvcGluZGV4
+IGhlbHAKUHJpbnQgYSB1c2FnZSBtZXNzYWdlIHN1bW1hcml6aW5nIHRoZSBtb3N0
+IHVzZWZ1bCBjb21tYW5kIGxpbmUgb3B0aW9ucy4KTm90ZSB0aGF0IHlvdSBjYW5u
+b3QgYWJicmV2aWF0ZSB0aGlzIGNvbW1hbmQuCgpAaXRlbSAtLXdhcnJhbnR5CkBv
+cGluZGV4IHdhcnJhbnR5ClByaW50IHdhcnJhbnR5IGluZm9ybWF0aW9uLgoKQGl0
+ZW0gLS1kdW1wLW9wdGlvbnMKQG9waW5kZXggZHVtcC1vcHRpb25zClByaW50IGEg
+bGlzdCBvZiBhbGwgYXZhaWxhYmxlIG9wdGlvbnMgYW5kIGNvbW1hbmRzLiAgTm90
+ZSB0aGF0IHlvdSBjYW5ub3QKYWJicmV2aWF0ZSB0aGlzIGNvbW1hbmQuCkBlbmQg
+dGFibGUKCgpAYyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
+KioqKioqCkBjICoqKioqKioqICBPUEVSQVRJT05BTCBDT01NQU5EUyAgKioqKioq
+KioqKioKQGMgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
+KioqKgpAbm9kZSBPcGVyYXRpb25hbCBHUEcgQ29tbWFuZHMKQHN1YnNlY3Rpb24g
+Q29tbWFuZHMgdG8gc2VsZWN0IHRoZSB0eXBlIG9mIG9wZXJhdGlvbgoKCkB0YWJs
+ZSBAZ251cGd0YWJvcHQKCkBpdGVtIC0tc2lnbgpAaXRlbXggLXMKQG9waW5kZXgg
+c2lnbgpNYWtlIGEgc2lnbmF0dXJlLiBUaGlzIGNvbW1hbmQgbWF5IGJlIGNvbWJp
+bmVkIHdpdGggQG9wdGlvbnstLWVuY3J5cHR9Cihmb3IgYSBzaWduZWQgYW5kIGVu
+Y3J5cHRlZCBtZXNzYWdlKSwgQG9wdGlvbnstLXN5bW1ldHJpY30gKGZvciBhCnNp
+Z25lZCBhbmQgc3ltbWV0cmljYWxseSBlbmNyeXB0ZWQgbWVzc2FnZSksIG9yIEBv
+cHRpb257LS1lbmNyeXB0fSBhbmQKQG9wdGlvbnstLXN5bW1ldHJpY30gdG9nZXRo
+ZXIgKGZvciBhIHNpZ25lZCBtZXNzYWdlIHRoYXQgbWF5IGJlCmRlY3J5cHRlZCB2
+aWEgYSBzZWNyZXQga2V5IG9yIGEgcGFzc3BocmFzZSkuICBUaGUga2V5IHRvIGJl
+IHVzZWQgZm9yCnNpZ25pbmcgaXMgY2hvc2VuIGJ5IGRlZmF1bHQgb3IgY2FuIGJl
+IHNldCB3aXRoIHRoZQpAb3B0aW9uey0tbG9jYWwtdXNlcn0gYW5kIEBvcHRpb257
+LS1kZWZhdWx0LWtleX0gb3B0aW9ucy4KCkBpdGVtIC0tY2xlYXJzaWduCkBvcGlu
+ZGV4IGNsZWFyc2lnbgpNYWtlIGEgY2xlYXIgdGV4dCBzaWduYXR1cmUuICBUaGUg
+Y29udGVudCBpbiBhIGNsZWFyIHRleHQgc2lnbmF0dXJlIGlzCnJlYWRhYmxlIHdp
+dGhvdXQgYW55IHNwZWNpYWwgc29mdHdhcmUuIE9wZW5QR1Agc29mdHdhcmUgaXMg
+b25seSBuZWVkZWQKdG8gdmVyaWZ5IHRoZSBzaWduYXR1cmUuICBDbGVhciB0ZXh0
+IHNpZ25hdHVyZXMgbWF5IG1vZGlmeSBlbmQtb2YtbGluZQp3aGl0ZXNwYWNlIGZv
+ciBwbGF0Zm9ybSBpbmRlcGVuZGVuY2UgYW5kIGFyZSBub3QgaW50ZW5kZWQgdG8g
+YmUKcmV2ZXJzaWJsZS4gIFRoZSBrZXkgdG8gYmUgdXNlZCBmb3Igc2lnbmluZyBp
+cyBjaG9zZW4gYnkgZGVmYXVsdCBvcgpjYW4gYmUgc2V0IHdpdGggdGhlIEBvcHRp
+b257LS1sb2NhbC11c2VyfSBhbmQgQG9wdGlvbnstLWRlZmF1bHQta2V5fQpvcHRp
+b25zLgoKCkBpdGVtIC0tZGV0YWNoLXNpZ24KQGl0ZW14IC1iCkBvcGluZGV4IGRl
+dGFjaC1zaWduCk1ha2UgYSBkZXRhY2hlZCBzaWduYXR1cmUuCgpAaXRlbSAtLWVu
+Y3J5cHQKQGl0ZW14IC1lCkBvcGluZGV4IGVuY3J5cHQKRW5jcnlwdCBkYXRhLiBU
+aGlzIG9wdGlvbiBtYXkgYmUgY29tYmluZWQgd2l0aCBAb3B0aW9uey0tc2lnbn0g
+KGZvciBhCnNpZ25lZCBhbmQgZW5jcnlwdGVkIG1lc3NhZ2UpLCBAb3B0aW9uey0t
+c3ltbWV0cmljfSAoZm9yIGEgbWVzc2FnZSB0aGF0Cm1heSBiZSBkZWNyeXB0ZWQg
+dmlhIGEgc2VjcmV0IGtleSBvciBhIHBhc3NwaHJhc2UpLCBvciBAb3B0aW9uey0t
+c2lnbn0KYW5kIEBvcHRpb257LS1zeW1tZXRyaWN9IHRvZ2V0aGVyIChmb3IgYSBz
+aWduZWQgbWVzc2FnZSB0aGF0IG1heSBiZQpkZWNyeXB0ZWQgdmlhIGEgc2VjcmV0
+IGtleSBvciBhIHBhc3NwaHJhc2UpLgoKQGl0ZW0gLS1zeW1tZXRyaWMKQGl0ZW14
+IC1jCkBvcGluZGV4IHN5bW1ldHJpYwpFbmNyeXB0IHdpdGggYSBzeW1tZXRyaWMg
+Y2lwaGVyIHVzaW5nIGEgcGFzc3BocmFzZS4gVGhlIGRlZmF1bHQKc3ltbWV0cmlj
+IGNpcGhlciB1c2VkIGlzIEB2YWx1ZXtHUEdTWU1FTkNBTEdPfSwgYnV0IG1heSBi
+ZSBjaG9zZW4gd2l0aCB0aGUKQG9wdGlvbnstLWNpcGhlci1hbGdvfSBvcHRpb24u
+IFRoaXMgb3B0aW9uIG1heSBiZSBjb21iaW5lZCB3aXRoCkBvcHRpb257LS1zaWdu
+fSAoZm9yIGEgc2lnbmVkIGFuZCBzeW1tZXRyaWNhbGx5IGVuY3J5cHRlZCBtZXNz
+YWdlKSwKQG9wdGlvbnstLWVuY3J5cHR9IChmb3IgYSBtZXNzYWdlIHRoYXQgbWF5
+IGJlIGRlY3J5cHRlZCB2aWEgYSBzZWNyZXQga2V5Cm9yIGEgcGFzc3BocmFzZSks
+IG9yIEBvcHRpb257LS1zaWdufSBhbmQgQG9wdGlvbnstLWVuY3J5cHR9IHRvZ2V0
+aGVyCihmb3IgYSBzaWduZWQgbWVzc2FnZSB0aGF0IG1heSBiZSBkZWNyeXB0ZWQg
+dmlhIGEgc2VjcmV0IGtleSBvciBhCnBhc3NwaHJhc2UpLgoKQGl0ZW0gLS1zdG9y
+ZQpAb3BpbmRleCBzdG9yZQpTdG9yZSBvbmx5IChtYWtlIGEgc2ltcGxlIFJGQzE5
+OTEgbGl0ZXJhbCBkYXRhIHBhY2tldCkuCgpAaXRlbSAtLWRlY3J5cHQKQGl0ZW14
+IC1kCkBvcGluZGV4IGRlY3J5cHQKRGVjcnlwdCB0aGUgZmlsZSBnaXZlbiBvbiB0
+aGUgY29tbWFuZCBsaW5lIChvciBTVERJTiBpZiBubyBmaWxlCmlzIHNwZWNpZmll
+ZCkgYW5kIHdyaXRlIGl0IHRvIFNURE9VVCAob3IgdGhlIGZpbGUgc3BlY2lmaWVk
+IHdpdGgKQG9wdGlvbnstLW91dHB1dH0pLiBJZiB0aGUgZGVjcnlwdGVkIGZpbGUg
+aXMgc2lnbmVkLCB0aGUgc2lnbmF0dXJlIGlzIGFsc28KdmVyaWZpZWQuIFRoaXMg
+Y29tbWFuZCBkaWZmZXJzIGZyb20gdGhlIGRlZmF1bHQgb3BlcmF0aW9uLCBhcyBp
+dCBuZXZlcgp3cml0ZXMgdG8gdGhlIGZpbGVuYW1lIHdoaWNoIGlzIGluY2x1ZGVk
+IGluIHRoZSBmaWxlIGFuZCBpdCByZWplY3RzCmZpbGVzIHdoaWNoIGRvbid0IGJl
+Z2luIHdpdGggYW4gZW5jcnlwdGVkIG1lc3NhZ2UuCgpAaXRlbSAtLXZlcmlmeQpA
+b3BpbmRleCB2ZXJpZnkKQXNzdW1lIHRoYXQgdGhlIGZpcnN0IGFyZ3VtZW50IGlz
+IGEgc2lnbmVkIGZpbGUgYW5kIHZlcmlmeSBpdCB3aXRob3V0CmdlbmVyYXRpbmcg
+YW55IG91dHB1dC4gIFdpdGggbm8gYXJndW1lbnRzLCB0aGUgc2lnbmF0dXJlIHBh
+Y2tldCBpcwpyZWFkIGZyb20gU1RESU4uICBJZiBvbmx5IGEgb25lIGFyZ3VtZW50
+IGlzIGdpdmVuLCBpdCBpcyBleHBlY3RlZCB0bwpiZSBhIGNvbXBsZXRlIHNpZ25h
+dHVyZS4KCldpdGggbW9yZSB0aGFuIDEgYXJndW1lbnQsIHRoZSBmaXJzdCBzaG91
+bGQgYmUgYSBkZXRhY2hlZCBzaWduYXR1cmUKYW5kIHRoZSByZW1haW5pbmcgZmls
+ZXMgYWtlIHVwIHRoZSB0aGUgc2lnbmVkIGRhdGEuIFRvIHJlYWQgdGhlIHNpZ25l
+ZApkYXRhIGZyb20gU1RESU4sIHVzZSBAc2FtcHstfSBhcyB0aGUgc2Vjb25kIGZp
+bGVuYW1lLiAgRm9yIHNlY3VyaXR5CnJlYXNvbnMgYSBkZXRhY2hlZCBzaWduYXR1
+cmUgY2Fubm90IHJlYWQgdGhlIHNpZ25lZCBtYXRlcmlhbCBmcm9tClNURElOIHdp
+dGhvdXQgZGVub3RpbmcgaXQgaW4gdGhlIGFib3ZlIHdheS4KCk5vdGU6IElmIHRo
+ZSBvcHRpb24gQG9wdGlvbnstLWJhdGNofSBpcyBub3QgdXNlZCwgQGNvbW1hbmR7
+QGdwZ25hbWV9Cm1heSBhc3N1bWUgdGhhdCBhIHNpbmdsZSBhcmd1bWVudCBpcyBh
+IGZpbGUgd2l0aCBhIGRldGFjaGVkIHNpZ25hdHVyZQphbmQgaXQgd2lsbCB0cnkg
+dG8gZmluZCBhIG1hdGNoaW5nIGRhdGEgZmlsZSBieSBzdHJpcHBpbmcgY2VydGFp
+bgpzdWZmaXhlcy4gIFVzaW5nIHRoaXMgaGlzdG9yaWNhbCBmZWF0dXJlIHRvIHZl
+cmlmeSBhIGRldGFjaGVkCnNpZ25hdHVyZSBpcyBzdHJvbmdseSBkaXNjb3VyYWdl
+ZDsgYWx3YXlzIHNwZWNpZnkgdGhlIGRhdGEgZmlsZSB0b28uCgpOb3RlOiBXaGVu
+IHZlcmlmeWluZyBhIGNsZWFydGV4dCBzaWduYXR1cmUsIEBjb21tYW5ke2dwZ30g
+dmVyaWZpZXMKb25seSB3aGF0IG1ha2VzIHVwIHRoZSBjbGVhcnRleHQgc2lnbmVk
+IGRhdGEgYW5kIG5vdCBhbnkgZXh0cmEgZGF0YQpvdXRzaWRlIG9mIHRoZSBjbGVh
+cnRleHQgc2lnbmF0dXJlIG9yIGhlYWRlciBsaW5lcyBmb2xsb3dpbmcgZGlyZWN0
+bHkKdGhlIGRhc2ggbWFya2VyIGxpbmUuICBUaGUgb3B0aW9uIEBjb2Rley0tb3V0
+cHV0fSBtYXkgYmUgdXNlZCB0byB3cml0ZQpvdXQgdGhlIGFjdHVhbCBzaWduZWQg
+ZGF0YTsgYnV0IHRoZXJlIGFyZSBvdGhlciBwaXRmYWxscyB3aXRoIHRoaXMKZm9y
+bWF0IGFzIHdlbGwuICBJdCBpcyBzdWdnZXN0ZWQgdG8gYXZvaWQgY2xlYXJ0ZXh0
+IHNpZ25hdHVyZXMgaW4KZmF2b3Igb2YgZGV0YWNoZWQgc2lnbmF0dXJlcy4KCkBp
+dGVtIC0tbXVsdGlmaWxlCkBvcGluZGV4IG11bHRpZmlsZQpUaGlzIG1vZGlmaWVz
+IGNlcnRhaW4gb3RoZXIgY29tbWFuZHMgdG8gYWNjZXB0IG11bHRpcGxlIGZpbGVz
+IGZvcgpwcm9jZXNzaW5nIG9uIHRoZSBjb21tYW5kIGxpbmUgb3IgcmVhZCBmcm9t
+IFNURElOIHdpdGggZWFjaCBmaWxlbmFtZSBvbgphIHNlcGFyYXRlIGxpbmUuIFRo
+aXMgYWxsb3dzIGZvciBtYW55IGZpbGVzIHRvIGJlIHByb2Nlc3NlZCBhdApvbmNl
+LiBAb3B0aW9uey0tbXVsdGlmaWxlfSBtYXkgY3VycmVudGx5IGJlIHVzZWQgYWxv
+bmcgd2l0aApAb3B0aW9uey0tdmVyaWZ5fSwgQG9wdGlvbnstLWVuY3J5cHR9LCBh
+bmQgQG9wdGlvbnstLWRlY3J5cHR9LiBOb3RlIHRoYXQKQG9wdGlvbnstLW11bHRp
+ZmlsZSAtLXZlcmlmeX0gbWF5IG5vdCBiZSB1c2VkIHdpdGggZGV0YWNoZWQgc2ln
+bmF0dXJlcy4KCkBpdGVtIC0tdmVyaWZ5LWZpbGVzCkBvcGluZGV4IHZlcmlmeS1m
+aWxlcwpJZGVudGljYWwgdG8gQG9wdGlvbnstLW11bHRpZmlsZSAtLXZlcmlmeX0u
+CgpAaXRlbSAtLWVuY3J5cHQtZmlsZXMKQG9waW5kZXggZW5jcnlwdC1maWxlcwpJ
+ZGVudGljYWwgdG8gQG9wdGlvbnstLW11bHRpZmlsZSAtLWVuY3J5cHR9LgoKQGl0
+ZW0gLS1kZWNyeXB0LWZpbGVzCkBvcGluZGV4IGRlY3J5cHQtZmlsZXMKSWRlbnRp
+Y2FsIHRvIEBvcHRpb257LS1tdWx0aWZpbGUgLS1kZWNyeXB0fS4KCkBpdGVtIC0t
+bGlzdC1rZXlzCkBpdGVteCAtawpAaXRlbXggLS1saXN0LXB1YmxpYy1rZXlzCkBv
+cGluZGV4IGxpc3Qta2V5cwpMaXN0IGFsbCBrZXlzIGZyb20gdGhlIHB1YmxpYyBr
+ZXlyaW5ncywgb3IganVzdCB0aGUga2V5cyBnaXZlbiBvbiB0aGUKY29tbWFuZCBs
+aW5lLgoKQXZvaWQgdXNpbmcgdGhlIG91dHB1dCBvZiB0aGlzIGNvbW1hbmQgaW4g
+c2NyaXB0cyBvciBvdGhlciBwcm9ncmFtcyBhcwppdCBpcyBsaWtlbHkgdG8gY2hh
+bmdlIGFzIEdudVBHIGNoYW5nZXMuIFNlZSBAb3B0aW9uey0td2l0aC1jb2xvbnN9
+IGZvciBhCm1hY2hpbmUtcGFyc2VhYmxlIGtleSBsaXN0aW5nIGNvbW1hbmQgdGhh
+dCBpcyBhcHByb3ByaWF0ZSBmb3IgdXNlIGluCnNjcmlwdHMgYW5kIG90aGVyIHBy
+b2dyYW1zLgoKQGl0ZW0gLS1saXN0LXNlY3JldC1rZXlzCkBpdGVteCAtSwpAb3Bp
+bmRleCBsaXN0LXNlY3JldC1rZXlzCkxpc3QgYWxsIGtleXMgZnJvbSB0aGUgc2Vj
+cmV0IGtleXJpbmdzLCBvciBqdXN0IHRoZSBvbmVzIGdpdmVuIG9uIHRoZQpjb21t
+YW5kIGxpbmUuIEEgQGNvZGV7I30gYWZ0ZXIgdGhlIGxldHRlcnMgQGNvZGV7c2Vj
+fSBtZWFucyB0aGF0IHRoZQpzZWNyZXQga2V5IGlzIG5vdCB1c2FibGUgKGZvciBl
+eGFtcGxlLCBpZiBpdCB3YXMgY3JlYXRlZCB2aWEKQG9wdGlvbnstLWV4cG9ydC1z
+ZWNyZXQtc3Via2V5c30pLgoKQGl0ZW0gLS1saXN0LXNpZ3MKQG9waW5kZXggbGlz
+dC1zaWdzClNhbWUgYXMgQG9wdGlvbnstLWxpc3Qta2V5c30sIGJ1dCB0aGUgc2ln
+bmF0dXJlcyBhcmUgbGlzdGVkIHRvby4KVGhpcyBjb21tYW5kIGhhcyB0aGUgc2Ft
+ZSBlZmZlY3QgYXMKdXNpbmcgQG9wdGlvbnstLWxpc3Qta2V5c30gd2l0aCBAb3B0
+aW9uey0td2l0aC1zaWctbGlzdH0uCgpGb3IgZWFjaCBzaWduYXR1cmUgbGlzdGVk
+LCB0aGVyZSBhcmUgc2V2ZXJhbCBmbGFncyBpbiBiZXR3ZWVuIHRoZSAic2lnIgp0
+YWcgYW5kIGtleWlkLiBUaGVzZSBmbGFncyBnaXZlIGFkZGl0aW9uYWwgaW5mb3Jt
+YXRpb24gYWJvdXQgZWFjaApzaWduYXR1cmUuIEZyb20gbGVmdCB0byByaWdodCwg
+dGhleSBhcmUgdGhlIG51bWJlcnMgMS0zIGZvciBjZXJ0aWZpY2F0ZQpjaGVjayBs
+ZXZlbCAoc2VlIEBvcHRpb257LS1hc2stY2VydC1sZXZlbH0pLCAiTCIgZm9yIGEg
+bG9jYWwgb3IKbm9uLWV4cG9ydGFibGUgc2lnbmF0dXJlIChzZWUgQG9wdGlvbnst
+LWxzaWduLWtleX0pLCAiUiIgZm9yIGEKbm9uUmV2b2NhYmxlIHNpZ25hdHVyZSAo
+c2VlIHRoZSBAb3B0aW9uey0tZWRpdC1rZXl9IGNvbW1hbmQgIm5yc2lnbiIpLAoi
+UCIgZm9yIGEgc2lnbmF0dXJlIHRoYXQgY29udGFpbnMgYSBwb2xpY3kgVVJMIChz
+ZWUKQG9wdGlvbnstLWNlcnQtcG9saWN5LXVybH0pLCAiTiIgZm9yIGEgc2lnbmF0
+dXJlIHRoYXQgY29udGFpbnMgYQpub3RhdGlvbiAoc2VlIEBvcHRpb257LS1jZXJ0
+LW5vdGF0aW9ufSksICJYIiBmb3IgYW4gZVhwaXJlZCBzaWduYXR1cmUKKHNlZSBA
+b3B0aW9uey0tYXNrLWNlcnQtZXhwaXJlfSksIGFuZCB0aGUgbnVtYmVycyAxLTkg
+b3IgIlQiIGZvciAxMCBhbmQKYWJvdmUgdG8gaW5kaWNhdGUgdHJ1c3Qgc2lnbmF0
+dXJlIGxldmVscyAoc2VlIHRoZSBAb3B0aW9uey0tZWRpdC1rZXl9CmNvbW1hbmQg
+InRzaWduIikuCgpAaXRlbSAtLWNoZWNrLXNpZ3MKQG9waW5kZXggY2hlY2stc2ln
+cwpTYW1lIGFzIEBvcHRpb257LS1saXN0LXNpZ3N9LCBidXQgdGhlIHNpZ25hdHVy
+ZXMgYXJlIHZlcmlmaWVkLiAgTm90ZQp0aGF0IGZvciBwZXJmb3JtYW5jZSByZWFz
+b25zIHRoZSByZXZvY2F0aW9uIHN0YXR1cyBvZiBhIHNpZ25pbmcga2V5IGlzCm5v
+dCBzaG93bi4KVGhpcyBjb21tYW5kIGhhcyB0aGUgc2FtZSBlZmZlY3QgYXMKdXNp
+bmcgQG9wdGlvbnstLWxpc3Qta2V5c30gd2l0aCBAb3B0aW9uey0td2l0aC1zaWct
+Y2hlY2t9LgoKVGhlIHN0YXR1cyBvZiB0aGUgdmVyaWZpY2F0aW9uIGlzIGluZGlj
+YXRlZCBieSBhIGZsYWcgZGlyZWN0bHkgZm9sbG93aW5nCnRoZSAic2lnIiB0YWcg
+KGFuZCB0aHVzIGJlZm9yZSB0aGUgZmxhZ3MgZGVzY3JpYmVkIGFib3ZlIGZvcgpA
+b3B0aW9uey0tbGlzdC1zaWdzfSkuICBBICIhIiBpbmRpY2F0ZXMgdGhhdCB0aGUg
+c2lnbmF0dXJlIGhhcyBiZWVuCnN1Y2Nlc3NmdWxseSB2ZXJpZmllZCwgYSAiLSIg
+ZGVub3RlcyBhIGJhZCBzaWduYXR1cmUgYW5kIGEgIiUiIGlzIHVzZWQKaWYgYW4g
+ZXJyb3Igb2NjdXJyZWQgd2hpbGUgY2hlY2tpbmcgdGhlIHNpZ25hdHVyZSAoZS5n
+LiBhIG5vbiBzdXBwb3J0ZWQKYWxnb3JpdGhtKS4KCkBpdGVtIC0tbG9jYXRlLWtl
+eXMKQG9waW5kZXggbG9jYXRlLWtleXMKTG9jYXRlIHRoZSBrZXlzIGdpdmVuIGFz
+IGFyZ3VtZW50cy4gIFRoaXMgY29tbWFuZCBiYXNpY2FsbHkgdXNlcyB0aGUKc2Ft
+ZSBhbGdvcml0aG0gYXMgdXNlZCB3aGVuIGxvY2F0aW5nIGtleXMgZm9yIGVuY3J5
+cHRpb24gb3Igc2lnbmluZyBhbmQKbWF5IHRodXMgYmUgdXNlZCB0byBzZWUgd2hh
+dCBrZXlzIEBjb21tYW5ke0BncGduYW1lfSBtaWdodCB1c2UuICBJbgpwYXJ0aWN1
+bGFyIGV4dGVybmFsIG1ldGhvZHMgYXMgZGVmaW5lZCBieSBAb3B0aW9uey0tYXV0
+by1rZXktbG9jYXRlfSBtYXkKYmUgdXNlZCB0byBsb2NhdGUgYSBrZXkuICBPbmx5
+IHB1YmxpYyBrZXlzIGFyZSBsaXN0ZWQuCgpAaXRlbSAtLWZpbmdlcnByaW50CkBv
+cGluZGV4IGZpbmdlcnByaW50Ckxpc3QgYWxsIGtleXMgKG9yIHRoZSBzcGVjaWZp
+ZWQgb25lcykgYWxvbmcgd2l0aCB0aGVpcgpmaW5nZXJwcmludHMuIFRoaXMgaXMg
+dGhlIHNhbWUgb3V0cHV0IGFzIEBvcHRpb257LS1saXN0LWtleXN9IGJ1dCB3aXRo
+CnRoZSBhZGRpdGlvbmFsIG91dHB1dCBvZiBhIGxpbmUgd2l0aCB0aGUgZmluZ2Vy
+cHJpbnQuIE1heSBhbHNvIGJlCmNvbWJpbmVkIHdpdGggQG9wdGlvbnstLWxpc3Qt
+c2lnc30gb3IgQG9wdGlvbnstLWNoZWNrLXNpZ3N9LiAgSWYgdGhpcwpjb21tYW5k
+IGlzIGdpdmVuIHR3aWNlLCB0aGUgZmluZ2VycHJpbnRzIG9mIGFsbCBzZWNvbmRh
+cnkga2V5cyBhcmUKbGlzdGVkIHRvby4KCkBpdGVtIC0tbGlzdC1wYWNrZXRzCkBv
+cGluZGV4IGxpc3QtcGFja2V0cwpMaXN0IG9ubHkgdGhlIHNlcXVlbmNlIG9mIHBh
+Y2tldHMuIFRoaXMgaXMgbWFpbmx5IHVzZWZ1bCBmb3IKZGVidWdnaW5nLiAgV2hl
+biB1c2VkIHdpdGggb3B0aW9uIEBvcHRpb257LS12ZXJib3NlfSB0aGUgYWN0dWFs
+IE1QSQp2YWx1ZXMgYXJlIGR1bXBlZCBhbmQgbm90IG9ubHkgdGhlaXIgbGVuZ3Ro
+cy4KCgpAaXRlbSAtLWNhcmQtZWRpdApAb3BpbmRleCBjYXJkLWVkaXQKUHJlc2Vu
+dCBhIG1lbnUgdG8gd29yayB3aXRoIGEgc21hcnRjYXJkLiBUaGUgc3ViY29tbWFu
+ZCAiaGVscCIgcHJvdmlkZXMKYW4gb3ZlcnZpZXcgb24gYXZhaWxhYmxlIGNvbW1h
+bmRzLiBGb3IgYSBkZXRhaWxlZCBkZXNjcmlwdGlvbiwgcGxlYXNlCnNlZSB0aGUg
+Q2FyZCBIT1dUTyBhdApodHRwczovL2dudXBnLm9yZy9kb2N1bWVudGF0aW9uL2hv
+d3Rvcy5odG1sI0dudVBHLWNhcmRIT1dUTyAuCgpAaXRlbSAtLWNhcmQtc3RhdHVz
+CkBvcGluZGV4IGNhcmQtc3RhdHVzClNob3cgdGhlIGNvbnRlbnQgb2YgdGhlIHNt
+YXJ0IGNhcmQuCgpAaXRlbSAtLWNoYW5nZS1waW4KQG9waW5kZXggY2hhbmdlLXBp
+bgpQcmVzZW50IGEgbWVudSB0byBhbGxvdyBjaGFuZ2luZyB0aGUgUElOIG9mIGEg
+c21hcnRjYXJkLiBUaGlzCmZ1bmN0aW9uYWxpdHkgaXMgYWxzbyBhdmFpbGFibGUg
+YXMgdGhlIHN1YmNvbW1hbmQgInBhc3N3ZCIgd2l0aCB0aGUKQG9wdGlvbnstLWNh
+cmQtZWRpdH0gY29tbWFuZC4KCkBpdGVtIC0tZGVsZXRlLWtleXMgQGNvZGV7bmFt
+ZX0KQGl0ZW14IC0tZGVsZXRlLWtleXMgQGNvZGV7bmFtZX0KUmVtb3ZlIGtleSBm
+cm9tIHRoZSBwdWJsaWMga2V5cmluZy4gSW4gYmF0Y2ggbW9kZSBlaXRoZXIgQG9w
+dGlvbnstLXllc30gaXMKcmVxdWlyZWQgb3IgdGhlIGtleSBtdXN0IGJlIHNwZWNp
+ZmllZCBieSBmaW5nZXJwcmludC4gVGhpcyBpcyBhCnNhZmVndWFyZCBhZ2FpbnN0
+IGFjY2lkZW50YWwgZGVsZXRpb24gb2YgbXVsdGlwbGUga2V5cy4KCkBpdGVtIC0t
+ZGVsZXRlLXNlY3JldC1rZXlzIEBjb2Rle25hbWV9CkBvcGluZGV4IGRlbGV0ZS1z
+ZWNyZXQta2V5cwpSZW1vdmUga2V5IGZyb20gdGhlIHNlY3JldCBrZXlyaW5nLiBJ
+biBiYXRjaCBtb2RlIHRoZSBrZXkKbXVzdCBiZSBzcGVjaWZpZWQgYnkgZmluZ2Vy
+cHJpbnQuCgpAaXRlbSAtLWRlbGV0ZS1zZWNyZXQtYW5kLXB1YmxpYy1rZXkgQGNv
+ZGV7bmFtZX0KQG9waW5kZXggZGVsZXRlLXNlY3JldC1hbmQtcHVibGljLWtleQpT
+YW1lIGFzIEBvcHRpb257LS1kZWxldGUta2V5fSwgYnV0IGlmIGEgc2VjcmV0IGtl
+eSBleGlzdHMsIGl0IHdpbGwgYmUKcmVtb3ZlZCBmaXJzdC4gSW4gYmF0Y2ggbW9k
+ZSB0aGUga2V5IG11c3QgYmUgc3BlY2lmaWVkIGJ5IGZpbmdlcnByaW50LgoKQGl0
+ZW0gLS1leHBvcnQKQG9waW5kZXggZXhwb3J0CkVpdGhlciBleHBvcnQgYWxsIGtl
+eXMgZnJvbSBhbGwga2V5cmluZ3MgKGRlZmF1bHQga2V5cmluZ3MgYW5kIHRob3Nl
+CnJlZ2lzdGVyZWQgdmlhIG9wdGlvbiBAb3B0aW9uey0ta2V5cmluZ30pLCBvciBp
+ZiBhdCBsZWFzdCBvbmUgbmFtZSBpcyBnaXZlbiwKdGhvc2Ugb2YgdGhlIGdpdmVu
+IG5hbWUuIFRoZSBleHBvcnRlZCBrZXlzIGFyZSB3cml0dGVuIHRvIFNURE9VVCBv
+ciB0byB0aGUKZmlsZSBnaXZlbiB3aXRoIG9wdGlvbiBAb3B0aW9uey0tb3V0cHV0
+fS4gIFVzZSB0b2dldGhlciB3aXRoCkBvcHRpb257LS1hcm1vcn0gdG8gbWFpbCB0
+aG9zZSBrZXlzLgoKQGl0ZW0gLS1zZW5kLWtleXMgQGNvZGV7a2V5IElEc30KQG9w
+aW5kZXggc2VuZC1rZXlzClNpbWlsYXIgdG8gQG9wdGlvbnstLWV4cG9ydH0gYnV0
+IHNlbmRzIHRoZSBrZXlzIHRvIGEga2V5c2VydmVyLgpGaW5nZXJwcmludHMgbWF5
+IGJlIHVzZWQgaW5zdGVhZCBvZiBrZXkgSURzLiBPcHRpb24gQG9wdGlvbnstLWtl
+eXNlcnZlcn0KbXVzdCBiZSB1c2VkIHRvIGdpdmUgdGhlIG5hbWUgb2YgdGhpcyBr
+ZXlzZXJ2ZXIuIERvbid0IHNlbmQgeW91cgpjb21wbGV0ZSBrZXlyaW5nIHRvIGEg
+a2V5c2VydmVyIC0tLSBzZWxlY3Qgb25seSB0aG9zZSBrZXlzIHdoaWNoIGFyZSBu
+ZXcKb3IgY2hhbmdlZCBieSB5b3UuICBJZiBubyBrZXkgSURzIGFyZSBnaXZlbiwg
+QGNvbW1hbmR7Z3BnfSBkb2VzIG5vdGhpbmcuCgpAaXRlbSAtLWV4cG9ydC1zZWNy
+ZXQta2V5cwpAaXRlbXggLS1leHBvcnQtc2VjcmV0LXN1YmtleXMKQG9waW5kZXgg
+ZXhwb3J0LXNlY3JldC1rZXlzCkBvcGluZGV4IGV4cG9ydC1zZWNyZXQtc3Via2V5
+cwpTYW1lIGFzIEBvcHRpb257LS1leHBvcnR9LCBidXQgZXhwb3J0cyB0aGUgc2Vj
+cmV0IGtleXMgaW5zdGVhZC4gIFRoZQpleHBvcnRlZCBrZXlzIGFyZSB3cml0dGVu
+IHRvIFNURE9VVCBvciB0byB0aGUgZmlsZSBnaXZlbiB3aXRoIG9wdGlvbgpAb3B0
+aW9uey0tb3V0cHV0fS4gIFRoaXMgY29tbWFuZCBpcyBvZnRlbiB1c2VkIGFsb25n
+IHdpdGggdGhlIG9wdGlvbgpAb3B0aW9uey0tYXJtb3J9IHRvIGFsbG93IGVhc3kg
+cHJpbnRpbmcgb2YgdGhlIGtleSBmb3IgcGFwZXIgYmFja3VwOwpob3dldmVyIHRo
+ZSBleHRlcm5hbCB0b29sIEBjb21tYW5ke3BhcGVya2V5fSBkb2VzIGEgYmV0dGVy
+IGpvYiBmb3IKY3JlYXRpbmcgYmFja3VwcyBvbiBwYXBlci4gIE5vdGUgdGhhdCBl
+eHBvcnRpbmcgYSBzZWNyZXQga2V5IGNhbiBiZSBhCnNlY3VyaXR5IHJpc2sgaWYg
+dGhlIGV4cG9ydGVkIGtleXMgYXJlIHNlbmQgb3ZlciBhbiBpbnNlY3VyZSBjaGFu
+bmVsLgoKVGhlIHNlY29uZCBmb3JtIG9mIHRoZSBjb21tYW5kIGhhcyB0aGUgc3Bl
+Y2lhbCBwcm9wZXJ0eSB0byByZW5kZXIgdGhlCnNlY3JldCBwYXJ0IG9mIHRoZSBw
+cmltYXJ5IGtleSB1c2VsZXNzOyB0aGlzIGlzIGEgR05VIGV4dGVuc2lvbiB0bwpP
+cGVuUEdQIGFuZCBvdGhlciBpbXBsZW1lbnRhdGlvbnMgY2FuIG5vdCBiZSBleHBl
+Y3RlZCB0byBzdWNjZXNzZnVsbHkKaW1wb3J0IHN1Y2ggYSBrZXkuICBJdHMgaW50
+ZW5kZWQgdXNlIGlzIHRvIGdlbmVyYXRlZCBhIGZ1bGwga2V5IHdpdGgKYW4gYWRk
+aXRpb25hbCBzaWduaW5nIHN1YmtleSBvbiBhIGRlZGljYXRlZCBtYWNoaW5lIGFu
+ZCB0aGVuIHVzaW5nCnRoaXMgY29tbWFuZCB0byBleHBvcnQgdGhlIGtleSB3aXRo
+b3V0IHRoZSBwcmltYXJ5IGtleSB0byB0aGUgbWFpbgptYWNoaW5lLgoKR251UEcg
+bWF5IGFzayB5b3UgdG8gZW50ZXIgdGhlIHBhc3NwaHJhc2UgZm9yIHRoZSBrZXku
+ICBUaGlzIGlzCnJlcXVpcmVkIGJlY2F1c2UgdGhlIGludGVybmFsIHByb3RlY3Rp
+b24gbWV0aG9kIG9mIHRoZSBzZWNyZXQga2V5IGlzCmRpZmZlcmVudCBmcm9tIHRo
+ZSBvbmUgc3BlY2lmaWVkIGJ5IHRoZSBPcGVuUEdQIHByb3RvY29sLgoKQGl0ZW0g
+LS1leHBvcnQtc3NoLWtleQpAb3BpbmRleCBleHBvcnQtc3NoLWtleQpUaGlzIGNv
+bW1hbmQgaXMgdXNlZCB0byBleHBvcnQgYSBrZXkgaW4gdGhlIE9wZW5TU0ggcHVi
+bGljIGtleSBmb3JtYXQuCkl0IHJlcXVpcmVzIHRoZSBzcGVjaWZpY2F0aW9uIG9m
+IG9uZSBrZXkgYnkgdGhlIHVzdWFsIG1lYW5zIGFuZApleHBvcnRzIHRoZSBsYXRl
+c3QgdmFsaWQgc3Via2V5IHdoaWNoIGhhcyBhbiBhdXRoZW50aWNhdGlvbiBjYXBh
+YmlsaXR5CnRvIFNURE9VVCBvciB0byB0aGUgZmlsZSBnaXZlbiB3aXRoIG9wdGlv
+biBAb3B0aW9uey0tb3V0cHV0fS4gIFRoYXQKb3V0cHV0IGNhbiBkaXJlY3RseSBi
+ZSBhZGRlZCB0byBzc2gncyBAZmlsZXthdXRob3JpemVkX2tleX0gZmlsZS4KCkJ5
+IHNwZWNpZnlpbmcgdGhlIGtleSB0byBleHBvcnQgdXNpbmcgYSBrZXkgSUQgb3Ig
+YSBmaW5nZXJwcmludApzdWZmaXhlZCB3aXRoIGFuIGV4Y2xhbWF0aW9uIG1hcmsg
+KCEpLCBhIHNwZWNpZmljIHN1YmtleSBvciB0aGUKcHJpbWFyeSBrZXkgY2FuIGJl
+IGV4cG9ydGVkLiAgVGhpcyBkb2VzIG5vdCBldmVuIHJlcXVpcmUgdGhhdCB0aGUg
+a2V5CmhhcyB0aGUgYXV0aGVudGljYXRpb24gY2FwYWJpbGl0eSBmbGFnIHNldC4g
+IFRvIHZpZXcgdGhlIGNhcGFiaWxpdHkKZmxhZ3Mgb2YgYSBrZXkgdXNlIEBjb2Rl
+ey0tbGlzdC1vcHRpb25zIHNob3ctdXNhZ2V9IGFsb25nIHdpdGggYSBrZXkKbGlz
+dGluZyBjb21tYW5kLgoKQGl0ZW0gLS1pbXBvcnQKQGl0ZW14IC0tZmFzdC1pbXBv
+cnQKQG9waW5kZXggaW1wb3J0CkltcG9ydC9tZXJnZSBrZXlzLiBUaGlzIGFkZHMg
+dGhlIGdpdmVuIGtleXMgdG8gdGhlCmtleXJpbmcuIFRoZSBmYXN0IHZlcnNpb24g
+aXMgY3VycmVudGx5IGp1c3QgYSBzeW5vbnltLgoKVGhlcmUgYXJlIGEgZmV3IG90
+aGVyIG9wdGlvbnMgd2hpY2ggY29udHJvbCBob3cgdGhpcyBjb21tYW5kIHdvcmtz
+LgpNb3N0IG5vdGFibGUgaGVyZSBpcyB0aGUgQG9wdGlvbnstLWltcG9ydC1vcHRp
+b25zIG1lcmdlLW9ubHl9IG9wdGlvbgp3aGljaCBkb2VzIG5vdCBpbnNlcnQgbmV3
+IGtleXMgYnV0IGRvZXMgb25seSB0aGUgbWVyZ2luZyBvZiBuZXcKc2lnbmF0dXJl
+cywgdXNlci1JRHMgYW5kIHN1YmtleXMuCgpAaXRlbSAtLXJlY3Yta2V5cyBAY29k
+ZXtrZXkgSURzfQpAb3BpbmRleCByZWN2LWtleXMKSW1wb3J0IHRoZSBrZXlzIHdp
+dGggdGhlIGdpdmVuIGtleSBJRHMgZnJvbSBhIGtleXNlcnZlci4gT3B0aW9uCkBv
+cHRpb257LS1rZXlzZXJ2ZXJ9IG11c3QgYmUgdXNlZCB0byBnaXZlIHRoZSBuYW1l
+IG9mIHRoaXMga2V5c2VydmVyLgoKQGl0ZW0gLS1yZWZyZXNoLWtleXMKQG9waW5k
+ZXggcmVmcmVzaC1rZXlzClJlcXVlc3QgdXBkYXRlcyBmcm9tIGEga2V5c2VydmVy
+IGZvciBrZXlzIHRoYXQgYWxyZWFkeSBleGlzdCBvbiB0aGUKbG9jYWwga2V5cmlu
+Zy4gVGhpcyBpcyB1c2VmdWwgZm9yIHVwZGF0aW5nIGEga2V5IHdpdGggdGhlIGxh
+dGVzdApzaWduYXR1cmVzLCB1c2VyIElEcywgZXRjLiBDYWxsaW5nIHRoaXMgd2l0
+aCBubyBhcmd1bWVudHMgd2lsbCByZWZyZXNoCnRoZSBlbnRpcmUga2V5cmluZy4g
+T3B0aW9uIEBvcHRpb257LS1rZXlzZXJ2ZXJ9IG11c3QgYmUgdXNlZCB0byBnaXZl
+IHRoZQpuYW1lIG9mIHRoZSBrZXlzZXJ2ZXIgZm9yIGFsbCBrZXlzIHRoYXQgZG8g
+bm90IGhhdmUgcHJlZmVycmVkIGtleXNlcnZlcnMKc2V0IChzZWUgQG9wdGlvbnst
+LWtleXNlcnZlci1vcHRpb25zIGhvbm9yLWtleXNlcnZlci11cmx9KS4KCkBpdGVt
+IC0tc2VhcmNoLWtleXMgQGNvZGV7bmFtZXN9CkBvcGluZGV4IHNlYXJjaC1rZXlz
+ClNlYXJjaCB0aGUga2V5c2VydmVyIGZvciB0aGUgZ2l2ZW4gbmFtZXMuIE11bHRp
+cGxlIG5hbWVzIGdpdmVuIGhlcmUgd2lsbApiZSBqb2luZWQgdG9nZXRoZXIgdG8g
+Y3JlYXRlIHRoZSBzZWFyY2ggc3RyaW5nIGZvciB0aGUga2V5c2VydmVyLgpPcHRp
+b24gQG9wdGlvbnstLWtleXNlcnZlcn0gbXVzdCBiZSB1c2VkIHRvIGdpdmUgdGhl
+IG5hbWUgb2YgdGhpcwprZXlzZXJ2ZXIuICBLZXlzZXJ2ZXJzIHRoYXQgc3VwcG9y
+dCBkaWZmZXJlbnQgc2VhcmNoIG1ldGhvZHMgYWxsb3cgdXNpbmcKdGhlIHN5bnRh
+eCBzcGVjaWZpZWQgaW4gIkhvdyB0byBzcGVjaWZ5IGEgdXNlciBJRCIgYmVsb3cu
+IE5vdGUgdGhhdApkaWZmZXJlbnQga2V5c2VydmVyIHR5cGVzIHN1cHBvcnQgZGlm
+ZmVyZW50IHNlYXJjaCBtZXRob2RzLiBDdXJyZW50bHkKb25seSBMREFQIHN1cHBv
+cnRzIHRoZW0gYWxsLgoKQGl0ZW0gLS1mZXRjaC1rZXlzIEBjb2Rle1VSSXN9CkBv
+cGluZGV4IGZldGNoLWtleXMKUmV0cmlldmUga2V5cyBsb2NhdGVkIGF0IHRoZSBz
+cGVjaWZpZWQgVVJJcy4gTm90ZSB0aGF0IGRpZmZlcmVudAppbnN0YWxsYXRpb25z
+IG9mIEdudVBHIG1heSBzdXBwb3J0IGRpZmZlcmVudCBwcm90b2NvbHMgKEhUVFAs
+IEZUUCwKTERBUCwgZXRjLikKCkBpdGVtIC0tdXBkYXRlLXRydXN0ZGIKQG9waW5k
+ZXggdXBkYXRlLXRydXN0ZGIKRG8gdHJ1c3QgZGF0YWJhc2UgbWFpbnRlbmFuY2Uu
+IFRoaXMgY29tbWFuZCBpdGVyYXRlcyBvdmVyIGFsbCBrZXlzIGFuZApidWlsZHMg
+dGhlIFdlYiBvZiBUcnVzdC4gVGhpcyBpcyBhbiBpbnRlcmFjdGl2ZSBjb21tYW5k
+IGJlY2F1c2UgaXQgbWF5CmhhdmUgdG8gYXNrIGZvciB0aGUgIm93bmVydHJ1c3Qi
+IHZhbHVlcyBmb3Iga2V5cy4gVGhlIHVzZXIgaGFzIHRvIGdpdmUKYW4gZXN0aW1h
+dGlvbiBvZiBob3cgZmFyIHNoZSB0cnVzdHMgdGhlIG93bmVyIG9mIHRoZSBkaXNw
+bGF5ZWQga2V5IHRvCmNvcnJlY3RseSBjZXJ0aWZ5IChzaWduKSBvdGhlciBrZXlz
+LiBHbnVQRyBvbmx5IGFza3MgZm9yIHRoZSBvd25lcnRydXN0CnZhbHVlIGlmIGl0
+IGhhcyBub3QgeWV0IGJlZW4gYXNzaWduZWQgdG8gYSBrZXkuIFVzaW5nIHRoZQpA
+b3B0aW9uey0tZWRpdC1rZXl9IG1lbnUsIHRoZSBhc3NpZ25lZCB2YWx1ZSBjYW4g
+YmUgY2hhbmdlZCBhdCBhbnkgdGltZS4KCkBpdGVtIC0tY2hlY2stdHJ1c3RkYgpA
+b3BpbmRleCBjaGVjay10cnVzdGRiCkRvIHRydXN0IGRhdGFiYXNlIG1haW50ZW5h
+bmNlIHdpdGhvdXQgdXNlciBpbnRlcmFjdGlvbi4gRnJvbSB0aW1lIHRvCnRpbWUg
+dGhlIHRydXN0IGRhdGFiYXNlIG11c3QgYmUgdXBkYXRlZCBzbyB0aGF0IGV4cGly
+ZWQga2V5cyBvcgpzaWduYXR1cmVzIGFuZCB0aGUgcmVzdWx0aW5nIGNoYW5nZXMg
+aW4gdGhlIFdlYiBvZiBUcnVzdCBjYW4gYmUKdHJhY2tlZC4gTm9ybWFsbHksIEdu
+dVBHIHdpbGwgY2FsY3VsYXRlIHdoZW4gdGhpcyBpcyByZXF1aXJlZCBhbmQgZG8g
+aXQKYXV0b21hdGljYWxseSB1bmxlc3MgQG9wdGlvbnstLW5vLWF1dG8tY2hlY2st
+dHJ1c3RkYn0gaXMgc2V0LiBUaGlzCmNvbW1hbmQgY2FuIGJlIHVzZWQgdG8gZm9y
+Y2UgYSB0cnVzdCBkYXRhYmFzZSBjaGVjayBhdCBhbnkgdGltZS4gVGhlCnByb2Nl
+c3NpbmcgaXMgaWRlbnRpY2FsIHRvIHRoYXQgb2YgQG9wdGlvbnstLXVwZGF0ZS10
+cnVzdGRifSBidXQgaXQKc2tpcHMga2V5cyB3aXRoIGEgbm90IHlldCBkZWZpbmVk
+ICJvd25lcnRydXN0Ii4KCkZvciB1c2Ugd2l0aCBjcm9uIGpvYnMsIHRoaXMgY29t
+bWFuZCBjYW4gYmUgdXNlZCB0b2dldGhlciB3aXRoCkBvcHRpb257LS1iYXRjaH0g
+aW4gd2hpY2ggY2FzZSB0aGUgdHJ1c3QgZGF0YWJhc2UgY2hlY2sgaXMgZG9uZSBv
+bmx5IGlmCmEgY2hlY2sgaXMgbmVlZGVkLiBUbyBmb3JjZSBhIHJ1biBldmVuIGlu
+IGJhdGNoIG1vZGUgYWRkIHRoZSBvcHRpb24KQG9wdGlvbnstLXllc30uCgpAYW5j
+aG9ye29wdGlvbiAtLWV4cG9ydC1vd25lcnRydXN0fQpAaXRlbSAtLWV4cG9ydC1v
+d25lcnRydXN0CkBvcGluZGV4IGV4cG9ydC1vd25lcnRydXN0ClNlbmQgdGhlIG93
+bmVydHJ1c3QgdmFsdWVzIHRvIFNURE9VVC4gVGhpcyBpcyB1c2VmdWwgZm9yIGJh
+Y2t1cCBwdXJwb3NlcwphcyB0aGVzZSB2YWx1ZXMgYXJlIHRoZSBvbmx5IG9uZXMg
+d2hpY2ggY2FuJ3QgYmUgcmUtY3JlYXRlZCBmcm9tIGEKY29ycnVwdGVkIHRydXN0
+ZGIuICBFeGFtcGxlOgpAYyBtYW46LlJTCkBleGFtcGxlCiAgQGdwZ25hbWV7fSAt
+LWV4cG9ydC1vd25lcnRydXN0ID4gb3RydXN0LnR4dApAZW5kIGV4YW1wbGUKQGMg
+bWFuOi5SRQoKCkBpdGVtIC0taW1wb3J0LW93bmVydHJ1c3QKQG9waW5kZXggaW1w
+b3J0LW93bmVydHJ1c3QKVXBkYXRlIHRoZSB0cnVzdGRiIHdpdGggdGhlIG93bmVy
+dHJ1c3QgdmFsdWVzIHN0b3JlZCBpbiBAY29kZXtmaWxlc30gKG9yClNURElOIGlm
+IG5vdCBnaXZlbik7IGV4aXN0aW5nIHZhbHVlcyB3aWxsIGJlIG92ZXJ3cml0dGVu
+LiAgSW4gY2FzZSBvZiBhCnNldmVyZWx5IGRhbWFnZWQgdHJ1c3RkYiBhbmQgaWYg
+eW91IGhhdmUgYSByZWNlbnQgYmFja3VwIG9mIHRoZQpvd25lcnRydXN0IHZhbHVl
+cyAoZS5nLiBpbiB0aGUgZmlsZSBAZmlsZXtvdHJ1c3QudHh0fSwgeW91IG1heSBy
+ZS1jcmVhdGUKdGhlIHRydXN0ZGIgdXNpbmcgdGhlc2UgY29tbWFuZHM6CkBjIG1h
+bjouUlMKQGV4YW1wbGUKICBjZCB+Ly5nbnVwZwogIHJtIHRydXN0ZGIuZ3BnCiAg
+QGdwZ25hbWV7fSAtLWltcG9ydC1vd25lcnRydXN0IDwgb3RydXN0LnR4dApAZW5k
+IGV4YW1wbGUKQGMgbWFuOi5SRQoKCkBpdGVtIC0tcmVidWlsZC1rZXlkYi1jYWNo
+ZXMKQG9waW5kZXggcmVidWlsZC1rZXlkYi1jYWNoZXMKV2hlbiB1cGRhdGluZyBm
+cm9tIHZlcnNpb24gMS4wLjYgdG8gMS4wLjcgdGhpcyBjb21tYW5kIHNob3VsZCBi
+ZSB1c2VkCnRvIGNyZWF0ZSBzaWduYXR1cmUgY2FjaGVzIGluIHRoZSBrZXlyaW5n
+LiBJdCBtaWdodCBiZSBoYW5keSBpbiBvdGhlcgpzaXR1YXRpb25zIHRvby4KCkBp
+dGVtIC0tcHJpbnQtbWQgQGNvZGV7YWxnb30KQGl0ZW14IC0tcHJpbnQtbWRzCkBv
+cGluZGV4IHByaW50LW1kClByaW50IG1lc3NhZ2UgZGlnZXN0IG9mIGFsZ29yaXRo
+bSBBTEdPIGZvciBhbGwgZ2l2ZW4gZmlsZXMgb3IgU1RESU4uCldpdGggdGhlIHNl
+Y29uZCBmb3JtIChvciBhIGRlcHJlY2F0ZWQgIioiIGFzIGFsZ28pIGRpZ2VzdHMg
+Zm9yIGFsbAphdmFpbGFibGUgYWxnb3JpdGhtcyBhcmUgcHJpbnRlZC4KCkBpdGVt
+IC0tZ2VuLXJhbmRvbSBAY29kZXswfDF8Mn0gQGNvZGV7Y291bnR9CkBvcGluZGV4
+IGdlbi1yYW5kb20KRW1pdCBAdmFye2NvdW50fSByYW5kb20gYnl0ZXMgb2YgdGhl
+IGdpdmVuIHF1YWxpdHkgbGV2ZWwgMCwgMSBvciAyLiBJZgpAdmFye2NvdW50fSBp
+cyBub3QgZ2l2ZW4gb3IgemVybywgYW4gZW5kbGVzcyBzZXF1ZW5jZSBvZiByYW5k
+b20gYnl0ZXMKd2lsbCBiZSBlbWl0dGVkLiAgSWYgdXNlZCB3aXRoIEBvcHRpb257
+LS1hcm1vcn0gdGhlIG91dHB1dCB3aWxsIGJlCmJhc2U2NCBlbmNvZGVkLiAgUExF
+QVNFLCBkb24ndCB1c2UgdGhpcyBjb21tYW5kIHVubGVzcyB5b3Uga25vdyB3aGF0
+CnlvdSBhcmUgZG9pbmc7IGl0IG1heSByZW1vdmUgcHJlY2lvdXMgZW50cm9weSBm
+cm9tIHRoZSBzeXN0ZW0hCgpAaXRlbSAtLWdlbi1wcmltZSBAY29kZXttb2RlfSAg
+QGNvZGV7Yml0c30KQG9waW5kZXggZ2VuLXByaW1lClVzZSB0aGUgc291cmNlLCBM
+dWtlIDotKS4gVGhlIG91dHB1dCBmb3JtYXQgaXMgc3RpbGwgc3ViamVjdCB0byBj
+aGFuZ2UuCgoKQGl0ZW0gLS1lbmFybW9yCkBpdGVtIC0tZGVhcm1vcgpAb3BpbmRl
+eCBlbmFybW9yCkBvcGluZGV4IGRlYXJtb3IKUGFjayBvciB1bnBhY2sgYW4gYXJi
+aXRyYXJ5IGlucHV0IGludG8vZnJvbSBhbiBPcGVuUEdQIEFTQ0lJIGFybW9yLgpU
+aGlzIGlzIGEgR251UEcgZXh0ZW5zaW9uIHRvIE9wZW5QR1AgYW5kIGluIGdlbmVy
+YWwgbm90IHZlcnkgdXNlZnVsLgoKQGl0ZW0gLS10b2Z1LXNldC1wb2xpY3kgQGNv
+ZGV7YXV0b3xnb29kfHVua25vd258YmFkfGFza30gIEBjb2Rle2tleS4uLn0KQG9w
+aW5kZXggdG9mdS1zZXQtcG9saWN5ClNldCB0aGUgVE9GVSBwb2xpY3kgZm9yIGFs
+bCB0aGUgYmluZGluZ3MgYXNzb2NpYXRlZCB3aXRoIHRoZSBzcGVjaWZpZWQKa2V5
+cy4gIEZvciBtb3JlIGluZm9ybWF0aW9uIGFib3V0IHRoZSBtZWFuaW5nIG9mIHRo
+ZSBwb2xpY2llcywKQHB4cmVme3RydXN0LW1vZGVsLXRvZnV9LiAgVGhlIGtleXMg
+bWF5IGJlIHNwZWNpZmllZCBlaXRoZXIgYnkgdGhlaXIKZmluZ2VycHJpbnQgKHBy
+ZWZlcnJlZCkgb3IgdGhlaXIga2V5aWQuCgpAYyBAaXRlbSAtLXNlcnZlcgpAYyBA
+b3BpbmRleCBzZXJ2ZXIKQGMgUnVuIGdwZyBpbiBzZXJ2ZXIgbW9kZS4gIFRoaXMg
+ZmVhdHVyZSBpcyBub3QgeWV0IHJlYWR5IGZvciB1c2UgYW5kCkBjIHRodXMgbm90
+IGRvY3VtZW50ZWQuCgpAZW5kIHRhYmxlCgoKQGMgKioqKioqKioqKioqKioqKioq
+KioqKioqKioqKioqKioqKioqKioqKioqKgpAYyAqKioqKioqICBLRVkgTUFOR0VN
+RU5UIENPTU1BTkRTICAqKioqKioqKioqCkBjICoqKioqKioqKioqKioqKioqKioq
+KioqKioqKioqKioqKioqKioqKioqKioKQG5vZGUgT3BlblBHUCBLZXkgTWFuYWdl
+bWVudApAc3Vic2VjdGlvbiBIb3cgdG8gbWFuYWdlIHlvdXIga2V5cwoKVGhpcyBz
+ZWN0aW9uIGV4cGxhaW5zIHRoZSBtYWluIGNvbW1hbmRzIGZvciBrZXkgbWFuYWdl
+bWVudAoKQHRhYmxlIEBnbnVwZ3RhYm9wdAoKQGl0ZW0gLS1xdWljay1nZW4ta2V5
+IEBjb2Rle3VzZXItaWR9CkBvcGluZGV4IHF1aWNrLWdlbi1rZXkKVGhpcyBpcyBh
+IHNpbXBsZSBjb21tYW5kIHRvIGdlbmVyYXRlIGEgc3RhbmRhcmQga2V5IHdpdGgg
+b25lIHVzZXIgaWQuCkluIGNvbnRyYXN0IHRvIEBvcHRpb257LS1nZW4ta2V5fSB0
+aGUga2V5IGlzIGdlbmVyYXRlZCBkaXJlY3RseQp3aXRob3V0IHRoZSBuZWVkIHRv
+IGFuc3dlciBhIGJ1bmNoIG9mIHByb21wdHMuICBVbmxlc3MgdGhlIG9wdGlvbgpA
+b3B0aW9uey0teWVzfSBpcyBnaXZlbiwgdGhlIGtleSBjcmVhdGlvbiB3aWxsIGJl
+IGNhbmNlbGVkIGlmIHRoZQpnaXZlbiB1c2VyIGlkIGFscmVhZHkgZXhpc3RzIGlu
+IHRoZSBrZXkgcmluZy4KCklmIGludm9rZWQgZGlyZWN0bHkgb24gdGhlIGNvbnNv
+bGUgd2l0aG91dCBhbnkgc3BlY2lhbCBvcHRpb25zIGFuCmFuc3dlciB0byBhIGBg
+Q29udGludWU/Jycgc3R5bGUgY29uZmlybWF0aW9uIHByb21wdCBpcyByZXF1aXJl
+ZC4gIEluCmNhc2UgdGhlIHVzZXIgaWQgYWxyZWFkeSBleGlzdHMgaW4gdGhlIGtl
+eSByaW5nIGEgc2Vjb25kIHByb21wdCB0bwpmb3JjZSB0aGUgY3JlYXRpb24gb2Yg
+dGhlIGtleSB3aWxsIHNob3cgdXAuCgpJZiB0aGlzIGNvbW1hbmQgaXMgdXNlZCB3
+aXRoIEBvcHRpb257LS1iYXRjaH0sCkBvcHRpb257LS1waW5lbnRyeS1tb2RlfSBo
+YXMgYmVlbiBzZXQgdG8gQGNvZGV7bG9vcGJhY2t9LCBhbmQgb25lIG9mCnRoZSBw
+YXNzcGhyYXNlIG9wdGlvbnMgKEBvcHRpb257LS1wYXNzcGhyYXNlfSwKQG9wdGlv
+bnstLXBhc3NwaHJhc2UtZmR9LCBvciBAb3B0aW9ue3Bhc3NwaHJhc2UtZmlsZX0p
+IGlzIHVzZWQsIHRoZQpzdXBwbGllZCBwYXNzcGhyYXNlIGlzIHVzZWQgZm9yIHRo
+ZSBuZXcga2V5IGFuZCB0aGUgYWdlbnQgZG9lcyBub3QgYXNrCmZvciBpdC4gIFRv
+IGNyZWF0ZSBhIGtleSB3aXRob3V0IGFueSBwcm90ZWN0aW9uIEBjb2Rley0tcGFz
+c3BocmFzZSAnJ30KbWF5IGJlIHVzZWQuCgpAaXRlbSAtLWdlbi1rZXkKQG9waW5k
+ZXggZ2VuLWtleQpHZW5lcmF0ZSBhIG5ldyBrZXkgcGFpciB1c2luZyB0aGUgY3Vy
+cmVudCBkZWZhdWx0IHBhcmFtZXRlcnMuICBUaGlzIGlzCnRoZSBzdGFuZGFyZCBj
+b21tYW5kIHRvIGNyZWF0ZSBhIG5ldyBrZXkuCgpAaXRlbSAtLWZ1bGwtZ2VuLWtl
+eQpAb3BpbmRleCBnZW4ta2V5CkdlbmVyYXRlIGEgbmV3IGtleSBwYWlyIHdpdGgg
+ZGlhbG9ncyBmb3IgYWxsIG9wdGlvbnMuICBUaGlzIGlzIGFuCmV4dGVuZGVkIHZl
+cnNpb24gb2YgQG9wdGlvbnstLWdlbi1rZXl9LgoKVGhlcmUgaXMgYWxzbyBhIGZl
+YXR1cmUgd2hpY2ggYWxsb3dzIHlvdSB0byBjcmVhdGUga2V5cyBpbiBiYXRjaApt
+b2RlLiBTZWUgdGhlIHRoZSBtYW51YWwgc2VjdGlvbiBgYFVuYXR0ZW5kZWQga2V5
+IGdlbmVyYXRpb24nJyBvbiBob3cKdG8gdXNlIHRoaXMuCgpAaXRlbSAtLWdlbi1y
+ZXZva2UgQGNvZGV7bmFtZX0KQG9waW5kZXggZ2VuLXJldm9rZQpHZW5lcmF0ZSBh
+IHJldm9jYXRpb24gY2VydGlmaWNhdGUgZm9yIHRoZSBjb21wbGV0ZSBrZXkuIFRv
+IHJldm9rZQphIHN1YmtleSBvciBhIHNpZ25hdHVyZSwgdXNlIHRoZSBAb3B0aW9u
+ey0tZWRpdH0gY29tbWFuZC4KCkBpdGVtIC0tZGVzaWctcmV2b2tlIEBjb2Rle25h
+bWV9CkBvcGluZGV4IGRlc2lnLXJldm9rZQpHZW5lcmF0ZSBhIGRlc2lnbmF0ZWQg
+cmV2b2NhdGlvbiBjZXJ0aWZpY2F0ZSBmb3IgYSBrZXkuIFRoaXMgYWxsb3dzIGEK
+dXNlciAod2l0aCB0aGUgcGVybWlzc2lvbiBvZiB0aGUga2V5aG9sZGVyKSB0byBy
+ZXZva2Ugc29tZW9uZSBlbHNlJ3MKa2V5LgoKCkBpdGVtIC0tZWRpdC1rZXkKQG9w
+aW5kZXggZWRpdC1rZXkKUHJlc2VudCBhIG1lbnUgd2hpY2ggZW5hYmxlcyB5b3Ug
+dG8gZG8gbW9zdCBvZiB0aGUga2V5IG1hbmFnZW1lbnQKcmVsYXRlZCB0YXNrcy4g
+IEl0IGV4cGVjdHMgdGhlIHNwZWNpZmljYXRpb24gb2YgYSBrZXkgb24gdGhlIGNv
+bW1hbmQKbGluZS4KCkBjICoqKioqKioqIEJlZ2luIEVkaXQta2V5IE9wdGlvbnMg
+KioqKioqKioqKgpAdGFibGUgQGFzaXMKCiAgQGl0ZW0gdWlkIEBjb2Rle259CiAg
+QG9waW5kZXgga2V5ZWRpdDp1aWQKICBUb2dnbGUgc2VsZWN0aW9uIG9mIHVzZXIg
+SUQgb3IgcGhvdG9ncmFwaGljIHVzZXIgSUQgd2l0aCBpbmRleCBAY29kZXtufS4K
+ICBVc2UgQGNvZGV7Kn0gdG8gc2VsZWN0IGFsbCBhbmQgQGNvZGV7MH0gdG8gZGVz
+ZWxlY3QgYWxsLgoKICBAaXRlbSBrZXkgQGNvZGV7bn0KICBAb3BpbmRleCBrZXll
+ZGl0OmtleQogIFRvZ2dsZSBzZWxlY3Rpb24gb2Ygc3Via2V5IHdpdGggaW5kZXgg
+QGNvZGV7bn0gb3Iga2V5IElEIEBjb2Rle259LgogIFVzZSBAY29kZXsqfSB0byBz
+ZWxlY3QgYWxsIGFuZCBAY29kZXswfSB0byBkZXNlbGVjdCBhbGwuCgogIEBpdGVt
+IHNpZ24KICBAb3BpbmRleCBrZXllZGl0OnNpZ24KICBNYWtlIGEgc2lnbmF0dXJl
+IG9uIGtleSBvZiB1c2VyIEBjb2Rle25hbWV9IElmIHRoZSBrZXkgaXMgbm90IHll
+dAogIHNpZ25lZCBieSB0aGUgZGVmYXVsdCB1c2VyIChvciB0aGUgdXNlcnMgZ2l2
+ZW4gd2l0aCAtdSksIHRoZSBwcm9ncmFtCiAgZGlzcGxheXMgdGhlIGluZm9ybWF0
+aW9uIG9mIHRoZSBrZXkgYWdhaW4sIHRvZ2V0aGVyIHdpdGggaXRzCiAgZmluZ2Vy
+cHJpbnQgYW5kIGFza3Mgd2hldGhlciBpdCBzaG91bGQgYmUgc2lnbmVkLiBUaGlz
+IHF1ZXN0aW9uIGlzCiAgcmVwZWF0ZWQgZm9yIGFsbCB1c2VycyBzcGVjaWZpZWQg
+d2l0aAogIC11LgoKICBAaXRlbSBsc2lnbgogIEBvcGluZGV4IGtleWVkaXQ6bHNp
+Z24KICBTYW1lIGFzICJzaWduIiBidXQgdGhlIHNpZ25hdHVyZSBpcyBtYXJrZWQg
+YXMgbm9uLWV4cG9ydGFibGUgYW5kIHdpbGwKICB0aGVyZWZvcmUgbmV2ZXIgYmUg
+dXNlZCBieSBvdGhlcnMuIFRoaXMgbWF5IGJlIHVzZWQgdG8gbWFrZSBrZXlzCiAg
+dmFsaWQgb25seSBpbiB0aGUgbG9jYWwgZW52aXJvbm1lbnQuCgogIEBpdGVtIG5y
+c2lnbgogIEBvcGluZGV4IGtleWVkaXQ6bnJzaWduCiAgU2FtZSBhcyAic2lnbiIg
+YnV0IHRoZSBzaWduYXR1cmUgaXMgbWFya2VkIGFzIG5vbi1yZXZvY2FibGUgYW5k
+IGNhbgogIHRoZXJlZm9yZSBuZXZlciBiZSByZXZva2VkLgoKICBAaXRlbSB0c2ln
+bgogIEBvcGluZGV4IGtleWVkaXQ6dHNpZ24KICBNYWtlIGEgdHJ1c3Qgc2lnbmF0
+dXJlLiBUaGlzIGlzIGEgc2lnbmF0dXJlIHRoYXQgY29tYmluZXMgdGhlIG5vdGlv
+bnMKICBvZiBjZXJ0aWZpY2F0aW9uIChsaWtlIGEgcmVndWxhciBzaWduYXR1cmUp
+LCBhbmQgdHJ1c3QgKGxpa2UgdGhlCiAgInRydXN0IiBjb21tYW5kKS4gSXQgaXMg
+Z2VuZXJhbGx5IG9ubHkgdXNlZnVsIGluIGRpc3RpbmN0IGNvbW11bml0aWVzCiAg
+b3IgZ3JvdXBzLgpAZW5kIHRhYmxlCgpAYyBtYW46LlJTCk5vdGUgdGhhdCAibCIg
+KGZvciBsb2NhbCAvIG5vbi1leHBvcnRhYmxlKSwgIm5yIiAoZm9yIG5vbi1yZXZv
+Y2FibGUsCmFuZCAidCIgKGZvciB0cnVzdCkgbWF5IGJlIGZyZWVseSBtaXhlZCBh
+bmQgcHJlZml4ZWQgdG8gInNpZ24iIHRvCmNyZWF0ZSBhIHNpZ25hdHVyZSBvZiBh
+bnkgdHlwZSBkZXNpcmVkLgpAYyBtYW46LlJFCgpJZiB0aGUgb3B0aW9uIEBvcHRp
+b257LS1vbmx5LXNpZ24tdGV4dC1pZHN9IGlzIHNwZWNpZmllZCwgdGhlbiBhbnkK
+bm9uLXRleHQgYmFzZWQgdXNlciBpZHMgKGUuZy4sIHBob3RvIElEcykgd2lsbCBu
+b3QgYmUgc2VsZWN0ZWQgZm9yCnNpZ25pbmcuCgpAdGFibGUgQGFzaXMKCiAgQGl0
+ZW0gZGVsc2lnCiAgQG9waW5kZXgga2V5ZWRpdDpkZWxzaWcKICBEZWxldGUgYSBz
+aWduYXR1cmUuIE5vdGUgdGhhdCBpdCBpcyBub3QgcG9zc2libGUgdG8gcmV0cmFj
+dCBhIHNpZ25hdHVyZSwKICBvbmNlIGl0IGhhcyBiZWVuIHNlbmQgdG8gdGhlIHB1
+YmxpYyAoaS5lLiB0byBhIGtleXNlcnZlcikuICBJbiB0aGF0IGNhc2UKICB5b3Ug
+YmV0dGVyIHVzZSBAY29kZXtyZXZzaWd9LgoKICBAaXRlbSByZXZzaWcKICBAb3Bp
+bmRleCBrZXllZGl0OnJldnNpZwogIFJldm9rZSBhIHNpZ25hdHVyZS4gRm9yIGV2
+ZXJ5IHNpZ25hdHVyZSB3aGljaCBoYXMgYmVlbiBnZW5lcmF0ZWQgYnkKICBvbmUg
+b2YgdGhlIHNlY3JldCBrZXlzLCBHbnVQRyBhc2tzIHdoZXRoZXIgYSByZXZvY2F0
+aW9uIGNlcnRpZmljYXRlCiAgc2hvdWxkIGJlIGdlbmVyYXRlZC4KCiAgQGl0ZW0g
+Y2hlY2sKICBAb3BpbmRleCBrZXllZGl0OmNoZWNrCiAgQ2hlY2sgdGhlIHNpZ25h
+dHVyZXMgb24gYWxsIHNlbGVjdGVkIHVzZXIgSURzLiAgV2l0aCB0aGUgZXh0cmEK
+ICBvcHRpb24gQGNvZGV7c2VsZnNpZ30gb25seSBzZWxmLXNpZ25hdHVyZXMgYXJl
+IHNob3duLgoKICBAaXRlbSBhZGR1aWQKICBAb3BpbmRleCBrZXllZGl0OmFkZHVp
+ZAogIENyZWF0ZSBhbiBhZGRpdGlvbmFsIHVzZXIgSUQuCgogIEBpdGVtIGFkZHBo
+b3RvCiAgQG9waW5kZXgga2V5ZWRpdDphZGRwaG90bwogIENyZWF0ZSBhIHBob3Rv
+Z3JhcGhpYyB1c2VyIElELiBUaGlzIHdpbGwgcHJvbXB0IGZvciBhIEpQRUcgZmls
+ZSB0aGF0CiAgd2lsbCBiZSBlbWJlZGRlZCBpbnRvIHRoZSB1c2VyIElELiBOb3Rl
+IHRoYXQgYSB2ZXJ5IGxhcmdlIEpQRUcgd2lsbCBtYWtlCiAgZm9yIGEgdmVyeSBs
+YXJnZSBrZXkuIEFsc28gbm90ZSB0aGF0IHNvbWUgcHJvZ3JhbXMgd2lsbCBkaXNw
+bGF5IHlvdXIKICBKUEVHIHVuY2hhbmdlZCAoR251UEcpLCBhbmQgc29tZSBwcm9n
+cmFtcyB3aWxsIHNjYWxlIGl0IHRvIGZpdCBpbiBhCiAgZGlhbG9nIGJveCAoUEdQ
+KS4KCiAgQGl0ZW0gc2hvd3Bob3RvCiAgQG9waW5kZXgga2V5ZWRpdDpzaG93cGhv
+dG8KICBEaXNwbGF5IHRoZSBzZWxlY3RlZCBwaG90b2dyYXBoaWMgdXNlciBJRC4K
+CiAgQGl0ZW0gZGVsdWlkCiAgQG9waW5kZXgga2V5ZWRpdDpkZWx1aWQKICBEZWxl
+dGUgYSB1c2VyIElEIG9yIHBob3RvZ3JhcGhpYyB1c2VyIElELiAgTm90ZSB0aGF0
+IGl0IGlzIG5vdAogIHBvc3NpYmxlIHRvIHJldHJhY3QgYSB1c2VyIGlkLCBvbmNl
+IGl0IGhhcyBiZWVuIHNlbmQgdG8gdGhlIHB1YmxpYwogIChpLmUuIHRvIGEga2V5
+c2VydmVyKS4gIEluIHRoYXQgY2FzZSB5b3UgYmV0dGVyIHVzZSBAY29kZXtyZXZ1
+aWR9LgoKICBAaXRlbSByZXZ1aWQKICBAb3BpbmRleCBrZXllZGl0OnJldnVpZAog
+IFJldm9rZSBhIHVzZXIgSUQgb3IgcGhvdG9ncmFwaGljIHVzZXIgSUQuCgogIEBp
+dGVtIHByaW1hcnkKICBAb3BpbmRleCBrZXllZGl0OnByaW1hcnkKICBGbGFnIHRo
+ZSBjdXJyZW50IHVzZXIgaWQgYXMgdGhlIHByaW1hcnkgb25lLCByZW1vdmVzIHRo
+ZSBwcmltYXJ5IHVzZXIKICBpZCBmbGFnIGZyb20gYWxsIG90aGVyIHVzZXIgaWRz
+IGFuZCBzZXRzIHRoZSB0aW1lc3RhbXAgb2YgYWxsIGFmZmVjdGVkCiAgc2VsZi1z
+aWduYXR1cmVzIG9uZSBzZWNvbmQgYWhlYWQuIE5vdGUgdGhhdCBzZXR0aW5nIGEg
+cGhvdG8gdXNlciBJRAogIGFzIHByaW1hcnkgbWFrZXMgaXQgcHJpbWFyeSBvdmVy
+IG90aGVyIHBob3RvIHVzZXIgSURzLCBhbmQgc2V0dGluZyBhCiAgcmVndWxhciB1
+c2VyIElEIGFzIHByaW1hcnkgbWFrZXMgaXQgcHJpbWFyeSBvdmVyIG90aGVyIHJl
+Z3VsYXIgdXNlcgogIElEcy4KCiAgQGl0ZW0ga2V5c2VydmVyCiAgQG9waW5kZXgg
+a2V5ZWRpdDprZXlzZXJ2ZXIKICBTZXQgYSBwcmVmZXJyZWQga2V5c2VydmVyIGZv
+ciB0aGUgc3BlY2lmaWVkIHVzZXIgSUQocykuIFRoaXMgYWxsb3dzCiAgb3RoZXIg
+dXNlcnMgdG8ga25vdyB3aGVyZSB5b3UgcHJlZmVyIHRoZXkgZ2V0IHlvdXIga2V5
+IGZyb20uIFNlZQogIEBvcHRpb257LS1rZXlzZXJ2ZXItb3B0aW9ucyBob25vci1r
+ZXlzZXJ2ZXItdXJsfSBmb3IgbW9yZSBvbiBob3cgdGhpcwogIHdvcmtzLiAgU2V0
+dGluZyBhIHZhbHVlIG9mICJub25lIiByZW1vdmVzIGFuIGV4aXN0aW5nIHByZWZl
+cnJlZAogIGtleXNlcnZlci4KCiAgQGl0ZW0gbm90YXRpb24KICBAb3BpbmRleCBr
+ZXllZGl0Om5vdGF0aW9uCiAgU2V0IGEgbmFtZT12YWx1ZSBub3RhdGlvbiBmb3Ig
+dGhlIHNwZWNpZmllZCB1c2VyIElEKHMpLiBTZWUKICBAb3B0aW9uey0tY2VydC1u
+b3RhdGlvbn0gZm9yIG1vcmUgb24gaG93IHRoaXMgd29ya3MuIFNldHRpbmcgYSB2
+YWx1ZSBvZgogICJub25lIiByZW1vdmVzIGFsbCBub3RhdGlvbnMsIHNldHRpbmcg
+YSBub3RhdGlvbiBwcmVmaXhlZCB3aXRoIGEgbWludXMKICBzaWduICgtKSByZW1v
+dmVzIHRoYXQgbm90YXRpb24sIGFuZCBzZXR0aW5nIGEgbm90YXRpb24gbmFtZSAo
+d2l0aG91dCB0aGUKICA9dmFsdWUpIHByZWZpeGVkIHdpdGggYSBtaW51cyBzaWdu
+IHJlbW92ZXMgYWxsIG5vdGF0aW9ucyB3aXRoIHRoYXQgbmFtZS4KCiAgQGl0ZW0g
+cHJlZgogIEBvcGluZGV4IGtleWVkaXQ6cHJlZgogIExpc3QgcHJlZmVyZW5jZXMg
+ZnJvbSB0aGUgc2VsZWN0ZWQgdXNlciBJRC4gVGhpcyBzaG93cyB0aGUgYWN0dWFs
+CiAgcHJlZmVyZW5jZXMsIHdpdGhvdXQgaW5jbHVkaW5nIGFueSBpbXBsaWVkIHBy
+ZWZlcmVuY2VzLgoKICBAaXRlbSBzaG93cHJlZgogIEBvcGluZGV4IGtleWVkaXQ6
+c2hvd3ByZWYKICBNb3JlIHZlcmJvc2UgcHJlZmVyZW5jZXMgbGlzdGluZyBmb3Ig
+dGhlIHNlbGVjdGVkIHVzZXIgSUQuIFRoaXMgc2hvd3MKICB0aGUgcHJlZmVyZW5j
+ZXMgaW4gZWZmZWN0IGJ5IGluY2x1ZGluZyB0aGUgaW1wbGllZCBwcmVmZXJlbmNl
+cyBvZiAzREVTCiAgKGNpcGhlciksIFNIQS0xIChkaWdlc3QpLCBhbmQgVW5jb21w
+cmVzc2VkIChjb21wcmVzc2lvbikgaWYgdGhleSBhcmUKICBub3QgYWxyZWFkeSBp
+bmNsdWRlZCBpbiB0aGUgcHJlZmVyZW5jZSBsaXN0LiBJbiBhZGRpdGlvbiwgdGhl
+CiAgcHJlZmVycmVkIGtleXNlcnZlciBhbmQgc2lnbmF0dXJlIG5vdGF0aW9ucyAo
+aWYgYW55KSBhcmUgc2hvd24uCgogIEBpdGVtIHNldHByZWYgQGNvZGV7c3RyaW5n
+fQogIEBvcGluZGV4IGtleWVkaXQ6c2V0cHJlZgogIFNldCB0aGUgbGlzdCBvZiB1
+c2VyIElEIHByZWZlcmVuY2VzIHRvIEBjb2Rle3N0cmluZ30gZm9yIGFsbCAob3Ig
+anVzdAogIHRoZSBzZWxlY3RlZCkgdXNlciBJRHMuIENhbGxpbmcgc2V0cHJlZiB3
+aXRoIG5vIGFyZ3VtZW50cyBzZXRzIHRoZQogIHByZWZlcmVuY2UgbGlzdCB0byB0
+aGUgZGVmYXVsdCAoZWl0aGVyIGJ1aWx0LWluIG9yIHNldCB2aWEKICBAb3B0aW9u
+ey0tZGVmYXVsdC1wcmVmZXJlbmNlLWxpc3R9KSwgYW5kIGNhbGxpbmcgc2V0cHJl
+ZiB3aXRoICJub25lIgogIGFzIHRoZSBhcmd1bWVudCBzZXRzIGFuIGVtcHR5IHBy
+ZWZlcmVuY2UgbGlzdC4gVXNlIEBjb21tYW5ke0BncGduYW1lCiAgLS12ZXJzaW9u
+fSB0byBnZXQgYSBsaXN0IG9mIGF2YWlsYWJsZSBhbGdvcml0aG1zLiBOb3RlIHRo
+YXQgd2hpbGUgeW91CiAgY2FuIGNoYW5nZSB0aGUgcHJlZmVyZW5jZXMgb24gYW4g
+YXR0cmlidXRlIHVzZXIgSUQgKGFrYSAicGhvdG8gSUQiKSwKICBHbnVQRyBkb2Vz
+IG5vdCBzZWxlY3Qga2V5cyB2aWEgYXR0cmlidXRlIHVzZXIgSURzIHNvIHRoZXNl
+IHByZWZlcmVuY2VzCiAgd2lsbCBub3QgYmUgdXNlZCBieSBHbnVQRy4KCiAgV2hl
+biBzZXR0aW5nIHByZWZlcmVuY2VzLCB5b3Ugc2hvdWxkIGxpc3QgdGhlIGFsZ29y
+aXRobXMgaW4gdGhlIG9yZGVyCiAgd2hpY2ggeW91J2QgbGlrZSB0byBzZWUgdGhl
+bSB1c2VkIGJ5IHNvbWVvbmUgZWxzZSB3aGVuIGVuY3J5cHRpbmcgYQogIG1lc3Nh
+Z2UgdG8geW91ciBrZXkuICBJZiB5b3UgZG9uJ3QgaW5jbHVkZSAzREVTLCBpdCB3
+aWxsIGJlCiAgYXV0b21hdGljYWxseSBhZGRlZCBhdCB0aGUgZW5kLiAgTm90ZSB0
+aGF0IHRoZXJlIGFyZSBtYW55IGZhY3RvcnMgdGhhdAogIGdvIGludG8gY2hvb3Np
+bmcgYW4gYWxnb3JpdGhtIChmb3IgZXhhbXBsZSwgeW91ciBrZXkgbWF5IG5vdCBi
+ZSB0aGUKICBvbmx5IHJlY2lwaWVudCksIGFuZCBzbyB0aGUgcmVtb3RlIE9wZW5Q
+R1AgYXBwbGljYXRpb24gYmVpbmcgdXNlZCB0bwogIHNlbmQgdG8geW91IG1heSBv
+ciBtYXkgbm90IGZvbGxvdyB5b3VyIGV4YWN0IGNob3NlbiBvcmRlciBmb3IgYSBn
+aXZlbgogIG1lc3NhZ2UuICBJdCB3aWxsLCBob3dldmVyLCBvbmx5IGNob29zZSBh
+biBhbGdvcml0aG0gdGhhdCBpcyBwcmVzZW50CiAgb24gdGhlIHByZWZlcmVuY2Ug
+bGlzdCBvZiBldmVyeSByZWNpcGllbnQga2V5LiAgU2VlIGFsc28gdGhlCiAgSU5U
+RVJPUEVSQUJJTElUWSBXSVRIIE9USEVSIE9QRU5QR1AgUFJPR1JBTVMgc2VjdGlv
+biBiZWxvdy4KCiAgQGl0ZW0gYWRka2V5CiAgQG9waW5kZXgga2V5ZWRpdDphZGRr
+ZXkKICBBZGQgYSBzdWJrZXkgdG8gdGhpcyBrZXkuCgogIEBpdGVtIGFkZGNhcmRr
+ZXkKICBAb3BpbmRleCBrZXllZGl0OmFkZGNhcmRrZXkKICBHZW5lcmF0ZSBhIHN1
+YmtleSBvbiBhIGNhcmQgYW5kIGFkZCBpdCB0byB0aGlzIGtleS4KCiAgQGl0ZW0g
+a2V5dG9jYXJkCiAgQG9waW5kZXgga2V5ZWRpdDprZXl0b2NhcmQKICBUcmFuc2Zl
+ciB0aGUgc2VsZWN0ZWQgc2VjcmV0IHN1YmtleSAob3IgdGhlIHByaW1hcnkga2V5
+IGlmIG5vIHN1YmtleQogIGhhcyBiZWVuIHNlbGVjdGVkKSB0byBhIHNtYXJ0Y2Fy
+ZC4gVGhlIHNlY3JldCBrZXkgaW4gdGhlIGtleXJpbmcgd2lsbAogIGJlIHJlcGxh
+Y2VkIGJ5IGEgc3R1YiBpZiB0aGUga2V5IGNvdWxkIGJlIHN0b3JlZCBzdWNjZXNz
+ZnVsbHkgb24gdGhlCiAgY2FyZCBhbmQgeW91IHVzZSB0aGUgc2F2ZSBjb21tYW5k
+IGxhdGVyLiBPbmx5IGNlcnRhaW4ga2V5IHR5cGVzIG1heSBiZQogIHRyYW5zZmVy
+cmVkIHRvIHRoZSBjYXJkLiBBIHN1YiBtZW51IGFsbG93cyB5b3UgdG8gc2VsZWN0
+IG9uIHdoYXQgY2FyZAogIHRvIHN0b3JlIHRoZSBrZXkuIE5vdGUgdGhhdCBpdCBp
+cyBub3QgcG9zc2libGUgdG8gZ2V0IHRoYXQga2V5IGJhY2sKICBmcm9tIHRoZSBj
+YXJkIC0gaWYgdGhlIGNhcmQgZ2V0cyBicm9rZW4geW91ciBzZWNyZXQga2V5IHdp
+bGwgYmUgbG9zdAogIHVubGVzcyB5b3UgaGF2ZSBhIGJhY2t1cCBzb21ld2hlcmUu
+CgogIEBpdGVtIGJrdXB0b2NhcmQgQGNvZGV7ZmlsZX0KICBAb3BpbmRleCBrZXll
+ZGl0OmJrdXB0b2NhcmQKICBSZXN0b3JlIHRoZSBnaXZlbiBmaWxlIHRvIGEgY2Fy
+ZC4gVGhpcyBjb21tYW5kIG1heSBiZSB1c2VkIHRvIHJlc3RvcmUgYQogIGJhY2t1
+cCBrZXkgKGFzIGdlbmVyYXRlZCBkdXJpbmcgY2FyZCBpbml0aWFsaXphdGlvbikg
+dG8gYSBuZXcgY2FyZC4gSW4KICBhbG1vc3QgYWxsIGNhc2VzIHRoaXMgd2lsbCBi
+ZSB0aGUgZW5jcnlwdGlvbiBrZXkuIFlvdSBzaG91bGQgdXNlIHRoaXMKICBjb21t
+YW5kIG9ubHkgd2l0aCB0aGUgY29ycmVzcG9uZGluZyBwdWJsaWMga2V5IGFuZCBt
+YWtlIHN1cmUgdGhhdCB0aGUKICBmaWxlIGdpdmVuIGFzIGFyZ3VtZW50IGlzIGlu
+ZGVlZCB0aGUgYmFja3VwIHRvIHJlc3RvcmUuIFlvdSBzaG91bGQgdGhlbgogIHNl
+bGVjdCAyIHRvIHJlc3RvcmUgYXMgZW5jcnlwdGlvbiBrZXkuICBZb3Ugd2lsbCBm
+aXJzdCBiZSBhc2tlZCB0byBlbnRlcgogIHRoZSBwYXNzcGhyYXNlIG9mIHRoZSBi
+YWNrdXAga2V5IGFuZCB0aGVuIGZvciB0aGUgQWRtaW4gUElOIG9mIHRoZSBjYXJk
+LgoKICBAaXRlbSBkZWxrZXkKICBAb3BpbmRleCBrZXllZGl0OmRlbGtleQogIFJl
+bW92ZSBhIHN1YmtleSAoc2Vjb25kYXJ5IGtleSkuIE5vdGUgdGhhdCBpdCBpcyBu
+b3QgcG9zc2libGUgdG8gcmV0cmFjdAogIGEgc3Via2V5LCBvbmNlIGl0IGhhcyBi
+ZWVuIHNlbmQgdG8gdGhlIHB1YmxpYyAoaS5lLiB0byBhIGtleXNlcnZlcikuICBJ
+bgogIHRoYXQgY2FzZSB5b3UgYmV0dGVyIHVzZSBAY29kZXtyZXZrZXl9LgoKICBA
+aXRlbSByZXZrZXkKICBAb3BpbmRleCBrZXllZGl0OnJldmtleQogIFJldm9rZSBh
+IHN1YmtleS4KCiAgQGl0ZW0gZXhwaXJlCiAgQG9waW5kZXgga2V5ZWRpdDpleHBp
+cmUKICBDaGFuZ2UgdGhlIGtleSBvciBzdWJrZXkgZXhwaXJhdGlvbiB0aW1lLiBJ
+ZiBhIHN1YmtleSBpcyBzZWxlY3RlZCwgdGhlCiAgZXhwaXJhdGlvbiB0aW1lIG9m
+IHRoaXMgc3Via2V5IHdpbGwgYmUgY2hhbmdlZC4gV2l0aCBubyBzZWxlY3Rpb24s
+IHRoZQogIGtleSBleHBpcmF0aW9uIG9mIHRoZSBwcmltYXJ5IGtleSBpcyBjaGFu
+Z2VkLgoKICBAaXRlbSB0cnVzdAogIEBvcGluZGV4IGtleWVkaXQ6dHJ1c3QKICBD
+aGFuZ2UgdGhlIG93bmVyIHRydXN0IHZhbHVlIGZvciB0aGUga2V5LiBUaGlzIHVw
+ZGF0ZXMgdGhlIHRydXN0LWRiCiAgaW1tZWRpYXRlbHkgYW5kIG5vIHNhdmUgaXMg
+cmVxdWlyZWQuCgogIEBpdGVtIGRpc2FibGUKICBAaXRlbXggZW5hYmxlCiAgQG9w
+aW5kZXgga2V5ZWRpdDpkaXNhYmxlCiAgQG9waW5kZXgga2V5ZWRpdDplbmFibGUK
+ICBEaXNhYmxlIG9yIGVuYWJsZSBhbiBlbnRpcmUga2V5LiBBIGRpc2FibGVkIGtl
+eSBjYW4gbm90IG5vcm1hbGx5IGJlCiAgdXNlZCBmb3IgZW5jcnlwdGlvbi4KCiAg
+QGl0ZW0gYWRkcmV2b2tlcgogIEBvcGluZGV4IGtleWVkaXQ6YWRkcmV2b2tlcgog
+IEFkZCBhIGRlc2lnbmF0ZWQgcmV2b2tlciB0byB0aGUga2V5LiBUaGlzIHRha2Vz
+IG9uZSBvcHRpb25hbCBhcmd1bWVudDoKICAic2Vuc2l0aXZlIi4gSWYgYSBkZXNp
+Z25hdGVkIHJldm9rZXIgaXMgbWFya2VkIGFzIHNlbnNpdGl2ZSwgaXQgd2lsbAog
+IG5vdCBiZSBleHBvcnRlZCBieSBkZWZhdWx0IChzZWUgZXhwb3J0LW9wdGlvbnMp
+LgoKICBAaXRlbSBwYXNzd2QKICBAb3BpbmRleCBrZXllZGl0OnBhc3N3ZAogIENo
+YW5nZSB0aGUgcGFzc3BocmFzZSBvZiB0aGUgc2VjcmV0IGtleS4KCiAgQGl0ZW0g
+dG9nZ2xlCiAgQG9waW5kZXgga2V5ZWRpdDp0b2dnbGUKICBUaGlzIGlzIGR1bW15
+IGNvbW1hbmQgd2hpY2ggZXhpc3RzIG9ubHkgZm9yIGJhY2t3YXJkIGNvbXBhdGli
+aWxpdHkuCgogIEBpdGVtIGNsZWFuCiAgQG9waW5kZXgga2V5ZWRpdDpjbGVhbgog
+IENvbXBhY3QgKGJ5IHJlbW92aW5nIGFsbCBzaWduYXR1cmVzIGV4Y2VwdCB0aGUg
+c2VsZnNpZykgYW55IHVzZXIgSUQKICB0aGF0IGlzIG5vIGxvbmdlciB1c2FibGUg
+KGUuZy4gcmV2b2tlZCwgb3IgZXhwaXJlZCkuIFRoZW4sIHJlbW92ZSBhbnkKICBz
+aWduYXR1cmVzIHRoYXQgYXJlIG5vdCB1c2FibGUgYnkgdGhlIHRydXN0IGNhbGN1
+bGF0aW9ucy4KICBTcGVjaWZpY2FsbHksIHRoaXMgcmVtb3ZlcyBhbnkgc2lnbmF0
+dXJlIHRoYXQgZG9lcyBub3QgdmFsaWRhdGUsIGFueQogIHNpZ25hdHVyZSB0aGF0
+IGlzIHN1cGVyc2VkZWQgYnkgYSBsYXRlciBzaWduYXR1cmUsIHJldm9rZWQgc2ln
+bmF0dXJlcywKICBhbmQgc2lnbmF0dXJlcyBpc3N1ZWQgYnkga2V5cyB0aGF0IGFy
+ZSBub3QgcHJlc2VudCBvbiB0aGUga2V5cmluZy4KCiAgQGl0ZW0gbWluaW1pemUK
+ICBAb3BpbmRleCBrZXllZGl0Om1pbmltaXplCiAgTWFrZSB0aGUga2V5IGFzIHNt
+YWxsIGFzIHBvc3NpYmxlLiBUaGlzIHJlbW92ZXMgYWxsIHNpZ25hdHVyZXMgZnJv
+bQogIGVhY2ggdXNlciBJRCBleGNlcHQgZm9yIHRoZSBtb3N0IHJlY2VudCBzZWxm
+LXNpZ25hdHVyZS4KCiAgQGl0ZW0gY3Jvc3MtY2VydGlmeQogIEBvcGluZGV4IGtl
+eWVkaXQ6Y3Jvc3MtY2VydGlmeQogIEFkZCBjcm9zcy1jZXJ0aWZpY2F0aW9uIHNp
+Z25hdHVyZXMgdG8gc2lnbmluZyBzdWJrZXlzIHRoYXQgbWF5IG5vdAogIGN1cnJl
+bnRseSBoYXZlIHRoZW0uIENyb3NzLWNlcnRpZmljYXRpb24gc2lnbmF0dXJlcyBw
+cm90ZWN0IGFnYWluc3QgYQogIHN1YnRsZSBhdHRhY2sgYWdhaW5zdCBzaWduaW5n
+IHN1YmtleXMuIFNlZQogIEBvcHRpb257LS1yZXF1aXJlLWNyb3NzLWNlcnRpZmlj
+YXRpb259LiAgQWxsIG5ldyBrZXlzIGdlbmVyYXRlZCBoYXZlCiAgdGhpcyBzaWdu
+YXR1cmUgYnkgZGVmYXVsdCwgc28gdGhpcyBvcHRpb24gaXMgb25seSB1c2VmdWwg
+dG8gYnJpbmcKICBvbGRlciBrZXlzIHVwIHRvIGRhdGUuCgogIEBpdGVtIHNhdmUK
+ICBAb3BpbmRleCBrZXllZGl0OnNhdmUKICBTYXZlIGFsbCBjaGFuZ2VzIHRvIHRo
+ZSBrZXkgcmluZ3MgYW5kIHF1aXQuCgogIEBpdGVtIHF1aXQKICBAb3BpbmRleCBr
+ZXllZGl0OnF1aXQKICBRdWl0IHRoZSBwcm9ncmFtIHdpdGhvdXQgdXBkYXRpbmcg
+dGhlCiAga2V5IHJpbmdzLgpAZW5kIHRhYmxlCgpAYyBtYW46LlJTClRoZSBsaXN0
+aW5nIHNob3dzIHlvdSB0aGUga2V5IHdpdGggaXRzIHNlY29uZGFyeSBrZXlzIGFu
+ZCBhbGwgdXNlcgppZHMuICBUaGUgcHJpbWFyeSB1c2VyIGlkIGlzIGluZGljYXRl
+ZCBieSBhIGRvdCwgYW5kIHNlbGVjdGVkIGtleXMgb3IKdXNlciBpZHMgYXJlIGlu
+ZGljYXRlZCBieSBhbiBhc3Rlcmlzay4gIFRoZSB0cnVzdAp2YWx1ZSBpcyBkaXNw
+bGF5ZWQgd2l0aCB0aGUgcHJpbWFyeSBrZXk6IHRoZSBmaXJzdCBpcyB0aGUgYXNz
+aWduZWQgb3duZXIKdHJ1c3QgYW5kIHRoZSBzZWNvbmQgaXMgdGhlIGNhbGN1bGF0
+ZWQgdHJ1c3QgdmFsdWUuIExldHRlcnMgYXJlIHVzZWQgZm9yCnRoZSB2YWx1ZXM6
+CkBjIG1hbjouUkUKCkB0YWJsZSBAYXNpcwoKICBAaXRlbSAtCiAgTm8gb3duZXJ0
+cnVzdCBhc3NpZ25lZCAvIG5vdCB5ZXQgY2FsY3VsYXRlZC4KCiAgQGl0ZW0gZQog
+IFRydXN0CiAgY2FsY3VsYXRpb24gaGFzIGZhaWxlZDsgcHJvYmFibHkgZHVlIHRv
+IGFuIGV4cGlyZWQga2V5LgoKICBAaXRlbSBxCiAgTm90IGVub3VnaCBpbmZvcm1h
+dGlvbiBmb3IgY2FsY3VsYXRpb24uCgogIEBpdGVtIG4KICBOZXZlciB0cnVzdCB0
+aGlzIGtleS4KCiAgQGl0ZW0gbQogIE1hcmdpbmFsbHkgdHJ1c3RlZC4KCiAgQGl0
+ZW0gZgogIEZ1bGx5IHRydXN0ZWQuCgogIEBpdGVtIHUKICBVbHRpbWF0ZWx5IHRy
+dXN0ZWQuCgpAZW5kIHRhYmxlCkBjICoqKioqKioqIEVuZCBFZGl0LWtleSBPcHRp
+b25zICoqKioqKioqKioKCkBpdGVtIC0tc2lnbi1rZXkgQGNvZGV7bmFtZX0KQG9w
+aW5kZXggc2lnbi1rZXkKU2lnbnMgYSBwdWJsaWMga2V5IHdpdGggeW91ciBzZWNy
+ZXQga2V5LiBUaGlzIGlzIGEgc2hvcnRjdXQgdmVyc2lvbiBvZgp0aGUgc3ViY29t
+bWFuZCAic2lnbiIgZnJvbSBAb3B0aW9uey0tZWRpdH0uCgpAaXRlbSAtLWxzaWdu
+LWtleSBAY29kZXtuYW1lfQpAb3BpbmRleCBsc2lnbi1rZXkKU2lnbnMgYSBwdWJs
+aWMga2V5IHdpdGggeW91ciBzZWNyZXQga2V5IGJ1dCBtYXJrcyBpdCBhcwpub24t
+ZXhwb3J0YWJsZS4gVGhpcyBpcyBhIHNob3J0Y3V0IHZlcnNpb24gb2YgdGhlIHN1
+YmNvbW1hbmQgImxzaWduIgpmcm9tIEBvcHRpb257LS1lZGl0LWtleX0uCgpAaXRl
+bSAtLXF1aWNrLXNpZ24ta2V5IEBjb2Rle2Zwcn0gW0Bjb2Rle25hbWVzfV0KQGl0
+ZW14IC0tcXVpY2stbHNpZ24ta2V5IEBjb2Rle2Zwcn0gW0Bjb2Rle25hbWVzfV0K
+QG9waW5kZXggcXVpY2stc2lnbi1rZXkKQG9waW5kZXggcXVpY2stbHNpZ24ta2V5
+CkRpcmVjdGx5IHNpZ24gYSBrZXkgZnJvbSB0aGUgcGFzc3BocmFzZSB3aXRob3V0
+IGFueSBmdXJ0aGVyIHVzZXIKaW50ZXJhY3Rpb24uICBUaGUgQGNvZGV7ZnByfSBt
+dXN0IGJlIHRoZSB2ZXJpZmllZCBwcmltYXJ5IGZpbmdlcnByaW50Cm9mIGEga2V5
+IGluIHRoZSBsb2NhbCBrZXlyaW5nLiBJZiBubyBAY29kZXtuYW1lc30gYXJlIGdp
+dmVuLCBhbGwKdXNlZnVsIHVzZXIgaWRzIGFyZSBzaWduZWQ7IHdpdGggZ2l2ZW4g
+W0Bjb2Rle25hbWVzfV0gb25seSB1c2VmdWwgdXNlcgppZHMgbWF0Y2hpbmcgb25l
+IG9mIHRoZXNlcyBuYW1lcyBhcmUgc2lnbmVkLiAgVGhlIGNvbW1hbmQKQG9wdGlv
+bnstLXF1aWNrLWxzaWduLWtleX0gbWFya3MgdGhlIHNpZ25hdHVyZXMgYXMgbm9u
+LWV4cG9ydGFibGUuICBJZgpzdWNoIGEgbm9uLWV4cG9ydGFibGUgc2lnbmF0dXJl
+IGFscmVhZHkgZXhpc3RzIHRoZQpAb3B0aW9uey0tcXVpY2stc2lnbi1rZXl9IHR1
+cm5zIGl0IGludG8gYSBleHBvcnRhYmxlIHNpZ25hdHVyZS4KClRoaXMgY29tbWFu
+ZCB1c2VzIHJlYXNvbmFibGUgZGVmYXVsdHMgYW5kIHRodXMgZG9lcyBub3QgcHJv
+dmlkZSB0aGUKZnVsbCBmbGV4aWJpbGl0eSBvZiB0aGUgInNpZ24iIHN1YmNvbW1h
+bmQgZnJvbSBAb3B0aW9uey0tZWRpdC1rZXl9LgpJdHMgaW50ZW5kZWQgdXNlIGlz
+IHRvIGhlbHAgdW5hdHRlbmRlZCBrZXkgc2lnbmluZyBieSB1dGlsaXppbmcgYSBs
+aXN0Cm9mIHZlcmlmaWVkIGZpbmdlcnByaW50cy4KCkBpdGVtIC0tcXVpY2stYWRk
+dWlkICBAdmFye3VzZXItaWR9IEB2YXJ7bmV3LXVzZXItaWR9CkBvcGluZGV4IHF1
+aWNrLWFkZHVpZApUaGlzIGNvbW1hbmQgYWRkcyBhIG5ldyB1c2VyIGlkIHRvIGFu
+IGV4aXN0aW5nIGtleS4gIEluIGNvbnRyYXN0IHRvCnRoZSBpbnRlcmFjdGl2ZSBz
+dWItY29tbWFuZCBAY29kZXthZGR1aWR9IG9mIEBvcHRpb257LS1lZGl0LWtleX0g
+dGhlCkB2YXJ7bmV3LXVzZXItaWR9IGlzIGFkZGVkIHZlcmJhdGltIHdpdGggb25s
+eSBsZWFkaW5nIGFuZCB0cmFpbGluZwp3aGl0ZSBzcGFjZSByZW1vdmVkLCBpdCBp
+cyBleHBlY3RlZCB0byBiZSBVVEYtOCBlbmNvZGVkLCBhbmQgbm8gY2hlY2tzCm9u
+IGl0cyBmb3JtIGFyZSBhcHBsaWVkLgoKQGl0ZW0gLS1wYXNzd2QgQHZhcnt1c2Vy
+X2lkfQpAb3BpbmRleCBwYXNzd2QKQ2hhbmdlIHRoZSBwYXNzcGhyYXNlIG9mIHRo
+ZSBzZWNyZXQga2V5IGJlbG9uZ2luZyB0byB0aGUgY2VydGlmaWNhdGUKc3BlY2lm
+aWVkIGFzIEB2YXJ7dXNlcl9pZH0uICBUaGlzIGlzIGEgc2hvcnRjdXQgZm9yIHRo
+ZSBzdWItY29tbWFuZApAY29kZXtwYXNzd2R9IG9mIHRoZSBlZGl0IGtleSBtZW51
+LgoKQGVuZCB0YWJsZQoKCkBjICoqKioqKioqKioqKioqKioqKioqKioqKioqKioq
+KioqKioqKioqKioqKioKQGMgKioqKioqKioqKioqKioqICAgICAgICAgICAgKioq
+KioqKioqKioqKioqKgpAYyAqKioqKioqKioqKioqKiogIE9QVElPTlMgICAqKioq
+KioqKioqKioqKioqCkBjICoqKioqKioqKioqKioqKiAgICAgICAgICAgICoqKioq
+KioqKioqKioqKioKQGMgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
+KioqKioqKioqKgpAbWFuc2VjdCBvcHRpb25zCkBub2RlIEdQRyBPcHRpb25zCkBz
+ZWN0aW9uIE9wdGlvbiBTdW1tYXJ5CgpAY29tbWFuZHtAZ3BnbmFtZX0gZmVhdHVy
+ZXMgYSBidW5jaCBvZiBvcHRpb25zIHRvIGNvbnRyb2wgdGhlIGV4YWN0CmJlaGF2
+aW91ciBhbmQgdG8gY2hhbmdlIHRoZSBkZWZhdWx0IGNvbmZpZ3VyYXRpb24uCgpA
+bWVudQoqIEdQRyBDb25maWd1cmF0aW9uIE9wdGlvbnM6OiAgIEhvdyB0byBjaGFu
+Z2UgdGhlIGNvbmZpZ3VyYXRpb24uCiogR1BHIEtleSByZWxhdGVkIE9wdGlvbnM6
+OiAgICAgS2V5IHJlbGF0ZWQgb3B0aW9ucy4KKiBHUEcgSW5wdXQgYW5kIE91dHB1
+dDo6ICAgICAgICBJbnB1dCBhbmQgT3V0cHV0LgoqIE9wZW5QR1AgT3B0aW9uczo6
+ICAgICAgICAgICAgIE9wZW5QR1AgcHJvdG9jb2wgc3BlY2lmaWMgb3B0aW9ucy4K
+KiBDb21wbGlhbmNlIE9wdGlvbnM6OiAgICAgICAgICBDb21wbGlhbmNlIG9wdGlv
+bnMuCiogR1BHIEVzb3RlcmljIE9wdGlvbnM6OiAgICAgICAgRG9pbmcgdGhpbmdz
+IG9uZSB1c3VhbGx5IGRvbid0IHdhbnQgdG8gZG8uCiogRGVwcmVjYXRlZCBPcHRp
+b25zOjogICAgICAgICAgRGVwcmVjYXRlZCBvcHRpb25zLgpAZW5kIG1lbnUKCkxv
+bmcgb3B0aW9ucyBjYW4gYmUgcHV0IGluIGFuIG9wdGlvbnMgZmlsZSAoZGVmYXVs
+dAoifi8uZ251cGcvZ3BnLmNvbmYiKS4gU2hvcnQgb3B0aW9uIG5hbWVzIHdpbGwg
+bm90IHdvcmsgLSBmb3IgZXhhbXBsZSwKImFybW9yIiBpcyBhIHZhbGlkIG9wdGlv
+biBmb3IgdGhlIG9wdGlvbnMgZmlsZSwgd2hpbGUgImEiIGlzIG5vdC4gRG8gbm90
+CndyaXRlIHRoZSAyIGRhc2hlcywgYnV0IHNpbXBseSB0aGUgbmFtZSBvZiB0aGUg
+b3B0aW9uIGFuZCBhbnkgcmVxdWlyZWQKYXJndW1lbnRzLiBMaW5lcyB3aXRoIGEg
+aGFzaCAoJyMnKSBhcyB0aGUgZmlyc3Qgbm9uLXdoaXRlLXNwYWNlCmNoYXJhY3Rl
+ciBhcmUgaWdub3JlZC4gQ29tbWFuZHMgbWF5IGJlIHB1dCBpbiB0aGlzIGZpbGUg
+dG9vLCBidXQgdGhhdCBpcwpub3QgZ2VuZXJhbGx5IHVzZWZ1bCBhcyB0aGUgY29t
+bWFuZCB3aWxsIGV4ZWN1dGUgYXV0b21hdGljYWxseSB3aXRoCmV2ZXJ5IGV4ZWN1
+dGlvbiBvZiBncGcuCgpQbGVhc2UgcmVtZW1iZXIgdGhhdCBvcHRpb24gcGFyc2lu
+ZyBzdG9wcyBhcyBzb29uIGFzIGEgbm9uLW9wdGlvbiBpcwplbmNvdW50ZXJlZCwg
+eW91IGNhbiBleHBsaWNpdGx5IHN0b3AgcGFyc2luZyBieSB1c2luZyB0aGUgc3Bl
+Y2lhbCBvcHRpb24KQG9wdGlvbnstLX0uCgpAYyAqKioqKioqKioqKioqKioqKioq
+KioqKioqKioqKioqKioqKioqKioqKioqCkBjICoqKioqKioqICBDT05GSUdVUkFU
+SU9OIE9QVElPTlMgICoqKioqKioqKioKQGMgKioqKioqKioqKioqKioqKioqKioq
+KioqKioqKioqKioqKioqKioqKioqKgpAbm9kZSBHUEcgQ29uZmlndXJhdGlvbiBP
+cHRpb25zCkBzdWJzZWN0aW9uIEhvdyB0byBjaGFuZ2UgdGhlIGNvbmZpZ3VyYXRp
+b24KClRoZXNlIG9wdGlvbnMgYXJlIHVzZWQgdG8gY2hhbmdlIHRoZSBjb25maWd1
+cmF0aW9uIGFuZCBhcmUgdXN1YWxseSBmb3VuZAppbiB0aGUgb3B0aW9uIGZpbGUu
+CgpAdGFibGUgQGdudXBndGFib3B0CgpAaXRlbSAtLWRlZmF1bHQta2V5IEB2YXJ7
+bmFtZX0KQG9waW5kZXggZGVmYXVsdC1rZXkKVXNlIEB2YXJ7bmFtZX0gYXMgdGhl
+IGRlZmF1bHQga2V5IHRvIHNpZ24gd2l0aC4gSWYgdGhpcyBvcHRpb24gaXMgbm90
+CnVzZWQsIHRoZSBkZWZhdWx0IGtleSBpcyB0aGUgZmlyc3Qga2V5IGZvdW5kIGlu
+IHRoZSBzZWNyZXQga2V5cmluZy4KTm90ZSB0aGF0IEBvcHRpb257LXV9IG9yIEBv
+cHRpb257LS1sb2NhbC11c2VyfSBvdmVycmlkZXMgdGhpcyBvcHRpb24uClRoaXMg
+b3B0aW9uIG1heSBiZSBnaXZlbiBtdWx0aXBsZSB0aW1lcy4gIEluIHRoaXMgY2Fz
+ZSwgdGhlIGxhc3Qga2V5CmZvciB3aGljaCBhIHNlY3JldCBrZXkgaXMgYXZhaWxh
+YmxlIGlzIHVzZWQuICBJZiB0aGVyZSBpcyBubyBzZWNyZXQKa2V5IGF2YWlsYWJs
+ZSBmb3IgYW55IG9mIHRoZSBzcGVjaWZpZWQgdmFsdWVzLCBHbnVQRyB3aWxsIG5v
+dCBlbWl0IGFuCmVycm9yIG1lc3NhZ2UgYnV0IGNvbnRpbnVlIGFzIGlmIHRoaXMg
+b3B0aW9uIHdhc24ndCBnaXZlbi4KCkBpdGVtIC0tZGVmYXVsdC1yZWNpcGllbnQg
+QHZhcntuYW1lfQpAb3BpbmRleCBkZWZhdWx0LXJlY2lwaWVudApVc2UgQHZhcntu
+YW1lfSBhcyBkZWZhdWx0IHJlY2lwaWVudCBpZiBvcHRpb24gQG9wdGlvbnstLXJl
+Y2lwaWVudH0gaXMKbm90IHVzZWQgYW5kIGRvbid0IGFzayBpZiB0aGlzIGlzIGEg
+dmFsaWQgb25lLiBAdmFye25hbWV9IG11c3QgYmUKbm9uLWVtcHR5LgoKQGl0ZW0g
+LS1kZWZhdWx0LXJlY2lwaWVudC1zZWxmCkBvcGluZGV4IGRlZmF1bHQtcmVjaXBp
+ZW50LXNlbGYKVXNlIHRoZSBkZWZhdWx0IGtleSBhcyBkZWZhdWx0IHJlY2lwaWVu
+dCBpZiBvcHRpb24gQG9wdGlvbnstLXJlY2lwaWVudH0gaXMgbm90CnVzZWQgYW5k
+IGRvbid0IGFzayBpZiB0aGlzIGlzIGEgdmFsaWQgb25lLiBUaGUgZGVmYXVsdCBr
+ZXkgaXMgdGhlIGZpcnN0Cm9uZSBmcm9tIHRoZSBzZWNyZXQga2V5cmluZyBvciB0
+aGUgb25lIHNldCB3aXRoIEBvcHRpb257LS1kZWZhdWx0LWtleX0uCgpAaXRlbSAt
+LW5vLWRlZmF1bHQtcmVjaXBpZW50CkBvcGluZGV4IG5vLWRlZmF1bHQtcmVjaXBp
+ZW50ClJlc2V0IEBvcHRpb257LS1kZWZhdWx0LXJlY2lwaWVudH0gYW5kIEBvcHRp
+b257LS1kZWZhdWx0LXJlY2lwaWVudC1zZWxmfS4KCkBpdGVtIC12LCAtLXZlcmJv
+c2UKQG9waW5kZXggdmVyYm9zZQpHaXZlIG1vcmUgaW5mb3JtYXRpb24gZHVyaW5n
+IHByb2Nlc3NpbmcuIElmIHVzZWQKdHdpY2UsIHRoZSBpbnB1dCBkYXRhIGlzIGxp
+c3RlZCBpbiBkZXRhaWwuCgpAaXRlbSAtLW5vLXZlcmJvc2UKQG9waW5kZXggbm8t
+dmVyYm9zZQpSZXNldCB2ZXJib3NlIGxldmVsIHRvIDAuCgpAaXRlbSAtcSwgLS1x
+dWlldApAb3BpbmRleCBxdWlldApUcnkgdG8gYmUgYXMgcXVpZXQgYXMgcG9zc2li
+bGUuCgpAaXRlbSAtLWJhdGNoCkBpdGVteCAtLW5vLWJhdGNoCkBvcGluZGV4IGJh
+dGNoCkBvcGluZGV4IG5vLWJhdGNoClVzZSBiYXRjaCBtb2RlLiAgTmV2ZXIgYXNr
+LCBkbyBub3QgYWxsb3cgaW50ZXJhY3RpdmUgY29tbWFuZHMuCkBvcHRpb257LS1u
+by1iYXRjaH0gZGlzYWJsZXMgdGhpcyBvcHRpb24uICBOb3RlIHRoYXQgZXZlbiB3
+aXRoIGEKZmlsZW5hbWUgZ2l2ZW4gb24gdGhlIGNvbW1hbmQgbGluZSwgZ3BnIG1p
+Z2h0IHN0aWxsIG5lZWQgdG8gcmVhZCBmcm9tClNURElOIChpbiBwYXJ0aWN1bGFy
+IGlmIGdwZyBmaWd1cmVzIHRoYXQgdGhlIGlucHV0IGlzIGEKZGV0YWNoZWQgc2ln
+bmF0dXJlIGFuZCBubyBkYXRhIGZpbGUgaGFzIGJlZW4gc3BlY2lmaWVkKS4gIFRo
+dXMgaWYgeW91CmRvIG5vdCB3YW50IHRvIGZlZWQgZGF0YSB2aWEgU1RESU4sIHlv
+dSBzaG91bGQgY29ubmVjdCBTVERJTiB0bwpAZmlsZXsvZGV2L251bGx9LgoKQGl0
+ZW0gLS1uby10dHkKQG9waW5kZXggbm8tdHR5Ck1ha2Ugc3VyZSB0aGF0IHRoZSBU
+VFkgKHRlcm1pbmFsKSBpcyBuZXZlciB1c2VkIGZvciBhbnkgb3V0cHV0LgpUaGlz
+IG9wdGlvbiBpcyBuZWVkZWQgaW4gc29tZSBjYXNlcyBiZWNhdXNlIEdudVBHIHNv
+bWV0aW1lcyBwcmludHMKd2FybmluZ3MgdG8gdGhlIFRUWSBldmVuIGlmIEBvcHRp
+b257LS1iYXRjaH0gaXMgdXNlZC4KCkBpdGVtIC0teWVzCkBvcGluZGV4IHllcwpB
+c3N1bWUgInllcyIgb24gbW9zdCBxdWVzdGlvbnMuCgpAaXRlbSAtLW5vCkBvcGlu
+ZGV4IG5vCkFzc3VtZSAibm8iIG9uIG1vc3QgcXVlc3Rpb25zLgoKCkBpdGVtIC0t
+bGlzdC1vcHRpb25zIEBjb2Rle3BhcmFtZXRlcnN9CkBvcGluZGV4IGxpc3Qtb3B0
+aW9ucwpUaGlzIGlzIGEgc3BhY2Ugb3IgY29tbWEgZGVsaW1pdGVkIHN0cmluZyB0
+aGF0IGdpdmVzIG9wdGlvbnMgdXNlZCB3aGVuCmxpc3Rpbmcga2V5cyBhbmQgc2ln
+bmF0dXJlcyAodGhhdCBpcywgQG9wdGlvbnstLWxpc3Qta2V5c30sCkBvcHRpb257
+LS1saXN0LXNpZ3N9LCBAb3B0aW9uey0tbGlzdC1wdWJsaWMta2V5c30sCkBvcHRp
+b257LS1saXN0LXNlY3JldC1rZXlzfSwgYW5kIHRoZSBAb3B0aW9uey0tZWRpdC1r
+ZXl9IGZ1bmN0aW9ucykuCk9wdGlvbnMgY2FuIGJlIHByZXBlbmRlZCB3aXRoIGEg
+QG9wdGlvbntuby19IChhZnRlciB0aGUgdHdvIGRhc2hlcykgdG8KZ2l2ZSB0aGUg
+b3Bwb3NpdGUgbWVhbmluZy4gIFRoZSBvcHRpb25zIGFyZToKCkB0YWJsZSBAYXNp
+cwoKICBAaXRlbSBzaG93LXBob3RvcwogIEBvcGluZGV4IGxpc3Qtb3B0aW9uczpz
+aG93LXBob3RvcwogIENhdXNlcyBAb3B0aW9uey0tbGlzdC1rZXlzfSwgQG9wdGlv
+bnstLWxpc3Qtc2lnc30sCiAgQG9wdGlvbnstLWxpc3QtcHVibGljLWtleXN9LCBh
+bmQgQG9wdGlvbnstLWxpc3Qtc2VjcmV0LWtleXN9IHRvCiAgZGlzcGxheSBhbnkg
+cGhvdG8gSURzIGF0dGFjaGVkIHRvIHRoZSBrZXkuICBEZWZhdWx0cyB0byBuby4g
+U2VlIGFsc28KICBAb3B0aW9uey0tcGhvdG8tdmlld2VyfS4gIERvZXMgbm90IHdv
+cmsgd2l0aCBAb3B0aW9uey0td2l0aC1jb2xvbnN9OgogIHNlZSBAb3B0aW9uey0t
+YXR0cmlidXRlLWZkfSBmb3IgdGhlIGFwcHJvcHJpYXRlIHdheSB0byBnZXQgcGhv
+dG8gZGF0YQogIGZvciBzY3JpcHRzIGFuZCBvdGhlciBmcm9udGVuZHMuCgogIEBp
+dGVtIHNob3ctdXNhZ2UKICBAb3BpbmRleCBsaXN0LW9wdGlvbnM6c2hvdy11c2Fn
+ZQogIFNob3cgdXNhZ2UgaW5mb3JtYXRpb24gZm9yIGtleXMgYW5kIHN1YmtleXMg
+aW4gdGhlIHN0YW5kYXJkIGtleQogIGxpc3RpbmcuICBUaGlzIGlzIGEgbGlzdCBv
+ZiBsZXR0ZXJzIGluZGljYXRpbmcgdGhlIGFsbG93ZWQgdXNhZ2UgZm9yIGEKICBr
+ZXkgKEBjb2Rle0V9PWVuY3J5cHRpb24sIEBjb2Rle1N9PXNpZ25pbmcsIEBjb2Rl
+e0N9PWNlcnRpZmljYXRpb24sCiAgQGNvZGV7QX09YXV0aGVudGljYXRpb24pLiAg
+RGVmYXVsdHMgdG8gbm8uCgogIEBpdGVtIHNob3ctcG9saWN5LXVybHMKICBAb3Bp
+bmRleCBsaXN0LW9wdGlvbnM6c2hvdy1wb2xpY3ktdXJscwogIFNob3cgcG9saWN5
+IFVSTHMgaW4gdGhlIEBvcHRpb257LS1saXN0LXNpZ3N9IG9yIEBvcHRpb257LS1j
+aGVjay1zaWdzfQogIGxpc3RpbmdzLiAgRGVmYXVsdHMgdG8gbm8uCgogIEBpdGVt
+IHNob3ctbm90YXRpb25zCiAgQGl0ZW14IHNob3ctc3RkLW5vdGF0aW9ucwogIEBp
+dGVteCBzaG93LXVzZXItbm90YXRpb25zCiAgQG9waW5kZXggbGlzdC1vcHRpb25z
+OnNob3ctbm90YXRpb25zCiAgQG9waW5kZXggbGlzdC1vcHRpb25zOnNob3ctc3Rk
+LW5vdGF0aW9ucwogIEBvcGluZGV4IGxpc3Qtb3B0aW9uczpzaG93LXVzZXItbm90
+YXRpb25zCiAgU2hvdyBhbGwsIElFVEYgc3RhbmRhcmQsIG9yIHVzZXItZGVmaW5l
+ZCBzaWduYXR1cmUgbm90YXRpb25zIGluIHRoZQogIEBvcHRpb257LS1saXN0LXNp
+Z3N9IG9yIEBvcHRpb257LS1jaGVjay1zaWdzfSBsaXN0aW5ncy4gRGVmYXVsdHMg
+dG8gbm8uCgogIEBpdGVtIHNob3cta2V5c2VydmVyLXVybHMKICBAb3BpbmRleCBs
+aXN0LW9wdGlvbnM6c2hvdy1rZXlzZXJ2ZXItdXJscwogIFNob3cgYW55IHByZWZl
+cnJlZCBrZXlzZXJ2ZXIgVVJMIGluIHRoZSBAb3B0aW9uey0tbGlzdC1zaWdzfSBv
+cgogIEBvcHRpb257LS1jaGVjay1zaWdzfSBsaXN0aW5ncy4gRGVmYXVsdHMgdG8g
+bm8uCgogIEBpdGVtIHNob3ctdWlkLXZhbGlkaXR5CiAgQG9waW5kZXggbGlzdC1v
+cHRpb25zOnNob3ctdWlkLXZhbGlkaXR5CiAgRGlzcGxheSB0aGUgY2FsY3VsYXRl
+ZCB2YWxpZGl0eSBvZiB1c2VyIElEcyBkdXJpbmcga2V5IGxpc3RpbmdzLgogIERl
+ZmF1bHRzIHRvIHllcy4KCiAgQGl0ZW0gc2hvdy11bnVzYWJsZS11aWRzCiAgQG9w
+aW5kZXggbGlzdC1vcHRpb25zOnNob3ctdW51c2FibGUtdWlkcwogIFNob3cgcmV2
+b2tlZCBhbmQgZXhwaXJlZCB1c2VyIElEcyBpbiBrZXkgbGlzdGluZ3MuIERlZmF1
+bHRzIHRvIG5vLgoKICBAaXRlbSBzaG93LXVudXNhYmxlLXN1YmtleXMKICBAb3Bp
+bmRleCBsaXN0LW9wdGlvbnM6c2hvdy11bnVzYWJsZS1zdWJrZXlzCiAgU2hvdyBy
+ZXZva2VkIGFuZCBleHBpcmVkIHN1YmtleXMgaW4ga2V5IGxpc3RpbmdzLiBEZWZh
+dWx0cyB0byBuby4KCiAgQGl0ZW0gc2hvdy1rZXlyaW5nCiAgQG9waW5kZXggbGlz
+dC1vcHRpb25zOnNob3cta2V5cmluZwogIERpc3BsYXkgdGhlIGtleXJpbmcgbmFt
+ZSBhdCB0aGUgaGVhZCBvZiBrZXkgbGlzdGluZ3MgdG8gc2hvdyB3aGljaAogIGtl
+eXJpbmcgYSBnaXZlbiBrZXkgcmVzaWRlcyBvbi4gRGVmYXVsdHMgdG8gbm8uCgog
+IEBpdGVtIHNob3ctc2lnLWV4cGlyZQogIEBvcGluZGV4IGxpc3Qtb3B0aW9uczpz
+aG93LXNpZy1leHBpcmUKICBTaG93IHNpZ25hdHVyZSBleHBpcmF0aW9uIGRhdGVz
+IChpZiBhbnkpIGR1cmluZyBAb3B0aW9uey0tbGlzdC1zaWdzfSBvcgogIEBvcHRp
+b257LS1jaGVjay1zaWdzfSBsaXN0aW5ncy4gRGVmYXVsdHMgdG8gbm8uCgogIEBp
+dGVtIHNob3ctc2lnLXN1YnBhY2tldHMKICBAb3BpbmRleCBsaXN0LW9wdGlvbnM6
+c2hvdy1zaWctc3VicGFja2V0cwogIEluY2x1ZGUgc2lnbmF0dXJlIHN1YnBhY2tl
+dHMgaW4gdGhlIGtleSBsaXN0aW5nLiBUaGlzIG9wdGlvbiBjYW4gdGFrZSBhbgog
+IG9wdGlvbmFsIGFyZ3VtZW50IGxpc3Qgb2YgdGhlIHN1YnBhY2tldHMgdG8gbGlz
+dC4gSWYgbm8gYXJndW1lbnQgaXMKICBwYXNzZWQsIGxpc3QgYWxsIHN1YnBhY2tl
+dHMuIERlZmF1bHRzIHRvIG5vLiBUaGlzIG9wdGlvbiBpcyBvbmx5CiAgbWVhbmlu
+Z2Z1bCB3aGVuIHVzaW5nIEBvcHRpb257LS13aXRoLWNvbG9uc30gYWxvbmcgd2l0
+aAogIEBvcHRpb257LS1saXN0LXNpZ3N9IG9yIEBvcHRpb257LS1jaGVjay1zaWdz
+fS4KCkBlbmQgdGFibGUKCkBpdGVtIC0tdmVyaWZ5LW9wdGlvbnMgQGNvZGV7cGFy
+YW1ldGVyc30KQG9waW5kZXggdmVyaWZ5LW9wdGlvbnMKVGhpcyBpcyBhIHNwYWNl
+IG9yIGNvbW1hIGRlbGltaXRlZCBzdHJpbmcgdGhhdCBnaXZlcyBvcHRpb25zIHVz
+ZWQgd2hlbgp2ZXJpZnlpbmcgc2lnbmF0dXJlcy4gT3B0aW9ucyBjYW4gYmUgcHJl
+cGVuZGVkIHdpdGggYSBgbm8tJyB0byBnaXZlCnRoZSBvcHBvc2l0ZSBtZWFuaW5n
+LiBUaGUgb3B0aW9ucyBhcmU6CgpAdGFibGUgQGFzaXMKCiAgQGl0ZW0gc2hvdy1w
+aG90b3MKICBAb3BpbmRleCB2ZXJpZnktb3B0aW9uczpzaG93LXBob3RvcwogIERp
+c3BsYXkgYW55IHBob3RvIElEcyBwcmVzZW50IG9uIHRoZSBrZXkgdGhhdCBpc3N1
+ZWQgdGhlIHNpZ25hdHVyZS4KICBEZWZhdWx0cyB0byBuby4gU2VlIGFsc28gQG9w
+dGlvbnstLXBob3RvLXZpZXdlcn0uCgogIEBpdGVtIHNob3ctcG9saWN5LXVybHMK
+ICBAb3BpbmRleCB2ZXJpZnktb3B0aW9uczpzaG93LXBvbGljeS11cmxzCiAgU2hv
+dyBwb2xpY3kgVVJMcyBpbiB0aGUgc2lnbmF0dXJlIGJlaW5nIHZlcmlmaWVkLiBE
+ZWZhdWx0cyB0byB5ZXMuCgogIEBpdGVtIHNob3ctbm90YXRpb25zCiAgQGl0ZW14
+IHNob3ctc3RkLW5vdGF0aW9ucwogIEBpdGVteCBzaG93LXVzZXItbm90YXRpb25z
+CiAgQG9waW5kZXggdmVyaWZ5LW9wdGlvbnM6c2hvdy1ub3RhdGlvbnMKICBAb3Bp
+bmRleCB2ZXJpZnktb3B0aW9uczpzaG93LXN0ZC1ub3RhdGlvbnMKICBAb3BpbmRl
+eCB2ZXJpZnktb3B0aW9uczpzaG93LXVzZXItbm90YXRpb25zCiAgU2hvdyBhbGws
+IElFVEYgc3RhbmRhcmQsIG9yIHVzZXItZGVmaW5lZCBzaWduYXR1cmUgbm90YXRp
+b25zIGluIHRoZQogIHNpZ25hdHVyZSBiZWluZyB2ZXJpZmllZC4gRGVmYXVsdHMg
+dG8gSUVURiBzdGFuZGFyZC4KCiAgQGl0ZW0gc2hvdy1rZXlzZXJ2ZXItdXJscwog
+IEBvcGluZGV4IHZlcmlmeS1vcHRpb25zOnNob3cta2V5c2VydmVyLXVybHMKICBT
+aG93IGFueSBwcmVmZXJyZWQga2V5c2VydmVyIFVSTCBpbiB0aGUgc2lnbmF0dXJl
+IGJlaW5nIHZlcmlmaWVkLgogIERlZmF1bHRzIHRvIHllcy4KCiAgQGl0ZW0gc2hv
+dy11aWQtdmFsaWRpdHkKICBAb3BpbmRleCB2ZXJpZnktb3B0aW9uczpzaG93LXVp
+ZC12YWxpZGl0eQogIERpc3BsYXkgdGhlIGNhbGN1bGF0ZWQgdmFsaWRpdHkgb2Yg
+dGhlIHVzZXIgSURzIG9uIHRoZSBrZXkgdGhhdCBpc3N1ZWQKICB0aGUgc2lnbmF0
+dXJlLiBEZWZhdWx0cyB0byB5ZXMuCgogIEBpdGVtIHNob3ctdW51c2FibGUtdWlk
+cwogIEBvcGluZGV4IHZlcmlmeS1vcHRpb25zOnNob3ctdW51c2FibGUtdWlkcwog
+IFNob3cgcmV2b2tlZCBhbmQgZXhwaXJlZCB1c2VyIElEcyBkdXJpbmcgc2lnbmF0
+dXJlIHZlcmlmaWNhdGlvbi4KICBEZWZhdWx0cyB0byBuby4KCiAgQGl0ZW0gc2hv
+dy1wcmltYXJ5LXVpZC1vbmx5CiAgQG9waW5kZXggdmVyaWZ5LW9wdGlvbnM6c2hv
+dy1wcmltYXJ5LXVpZC1vbmx5CiAgU2hvdyBvbmx5IHRoZSBwcmltYXJ5IHVzZXIg
+SUQgZHVyaW5nIHNpZ25hdHVyZSB2ZXJpZmljYXRpb24uICBUaGF0IGlzCiAgYWxs
+IHRoZSBBS0EgbGluZXMgYXMgd2VsbCBhcyBwaG90byBJZHMgYXJlIG5vdCBzaG93
+biB3aXRoIHRoZSBzaWduYXR1cmUKICB2ZXJpZmljYXRpb24gc3RhdHVzLgoKICBA
+aXRlbSBwa2EtbG9va3VwcwogIEBvcGluZGV4IHZlcmlmeS1vcHRpb25zOnBrYS1s
+b29rdXBzCiAgRW5hYmxlIFBLQSBsb29rdXBzIHRvIHZlcmlmeSBzZW5kZXIgYWRk
+cmVzc2VzLiBOb3RlIHRoYXQgUEtBIGlzIGJhc2VkCiAgb24gRE5TLCBhbmQgc28g
+ZW5hYmxpbmcgdGhpcyBvcHRpb24gbWF5IGRpc2Nsb3NlIGluZm9ybWF0aW9uIG9u
+IHdoZW4KICBhbmQgd2hhdCBzaWduYXR1cmVzIGFyZSB2ZXJpZmllZCBvciB0byB3
+aG9tIGRhdGEgaXMgZW5jcnlwdGVkLiBUaGlzCiAgaXMgc2ltaWxhciB0byB0aGUg
+IndlYiBidWciIGRlc2NyaWJlZCBmb3IgdGhlIGF1dG8ta2V5LXJldHJpZXZlCiAg
+ZmVhdHVyZS4KCiAgQGl0ZW0gcGthLXRydXN0LWluY3JlYXNlCiAgQG9waW5kZXgg
+dmVyaWZ5LW9wdGlvbnM6cGthLXRydXN0LWluY3JlYXNlCiAgUmFpc2UgdGhlIHRy
+dXN0IGluIGEgc2lnbmF0dXJlIHRvIGZ1bGwgaWYgdGhlIHNpZ25hdHVyZSBwYXNz
+ZXMgUEtBCiAgdmFsaWRhdGlvbi4gVGhpcyBvcHRpb24gaXMgb25seSBtZWFuaW5n
+ZnVsIGlmIHBrYS1sb29rdXBzIGlzIHNldC4KQGVuZCB0YWJsZQoKQGl0ZW0gLS1l
+bmFibGUtbGFyZ2UtcnNhCkBpdGVteCAtLWRpc2FibGUtbGFyZ2UtcnNhCkBvcGlu
+ZGV4IGVuYWJsZS1sYXJnZS1yc2EKQG9waW5kZXggZGlzYWJsZS1sYXJnZS1yc2EK
+V2l0aCAtLWdlbi1rZXkgYW5kIC0tYmF0Y2gsIGVuYWJsZSB0aGUgY3JlYXRpb24g
+b2YgbGFyZ2VyIFJTQSBzZWNyZXQKa2V5cyB0aGFuIGlzIGdlbmVyYWxseSByZWNv
+bW1lbmRlZCAodXAgdG8gODE5MiBiaXRzKS4gIFRoZXNlIGxhcmdlCmtleXMgYXJl
+IG1vcmUgZXhwZW5zaXZlIHRvIHVzZSwgYW5kIHRoZWlyIHNpZ25hdHVyZXMgYW5k
+CmNlcnRpZmljYXRpb25zIGFyZSBhbHNvIGxhcmdlci4KCkBpdGVtIC0tZW5hYmxl
+LWRzYTIKQGl0ZW14IC0tZGlzYWJsZS1kc2EyCkBvcGluZGV4IGVuYWJsZS1kc2Ey
+CkBvcGluZGV4IGRpc2FibGUtZHNhMgpFbmFibGUgaGFzaCB0cnVuY2F0aW9uIGZv
+ciBhbGwgRFNBIGtleXMgZXZlbiBmb3Igb2xkIERTQSBLZXlzIHVwIHRvCjEwMjQg
+Yml0LiAgVGhpcyBpcyBhbHNvIHRoZSBkZWZhdWx0IHdpdGggQG9wdGlvbnstLW9w
+ZW5wZ3B9LiAgTm90ZQp0aGF0IG9sZGVyIHZlcnNpb25zIG9mIEdudVBHIGFsc28g
+cmVxdWlyZWQgdGhpcyBmbGFnIHRvIGFsbG93IHRoZQpnZW5lcmF0aW9uIG9mIERT
+QSBsYXJnZXIgdGhhbiAxMDI0IGJpdC4KCkBpdGVtIC0tcGhvdG8tdmlld2VyIEBj
+b2Rle3N0cmluZ30KQG9waW5kZXggcGhvdG8tdmlld2VyClRoaXMgaXMgdGhlIGNv
+bW1hbmQgbGluZSB0aGF0IHNob3VsZCBiZSBydW4gdG8gdmlldyBhIHBob3RvIElE
+LiAiJWkiCndpbGwgYmUgZXhwYW5kZWQgdG8gYSBmaWxlbmFtZSBjb250YWluaW5n
+IHRoZSBwaG90by4gIiVJIiBkb2VzIHRoZQpzYW1lLCBleGNlcHQgdGhlIGZpbGUg
+d2lsbCBub3QgYmUgZGVsZXRlZCBvbmNlIHRoZSB2aWV3ZXIgZXhpdHMuCk90aGVy
+IGZsYWdzIGFyZSAiJWsiIGZvciB0aGUga2V5IElELCAiJUsiIGZvciB0aGUgbG9u
+ZyBrZXkgSUQsICIlZiIKZm9yIHRoZSBrZXkgZmluZ2VycHJpbnQsICIldCIgZm9y
+IHRoZSBleHRlbnNpb24gb2YgdGhlIGltYWdlIHR5cGUKKGUuZy4gImpwZyIpLCAi
+JVQiIGZvciB0aGUgTUlNRSB0eXBlIG9mIHRoZSBpbWFnZSAoZS5nLiAiaW1hZ2Uv
+anBlZyIpLAoiJXYiIGZvciB0aGUgc2luZ2xlLWNoYXJhY3RlciBjYWxjdWxhdGVk
+IHZhbGlkaXR5IG9mIHRoZSBpbWFnZSBiZWluZwp2aWV3ZWQgKGUuZy4gImYiKSwg
+IiVWIiBmb3IgdGhlIGNhbGN1bGF0ZWQgdmFsaWRpdHkgYXMgYSBzdHJpbmcgKGUu
+Zy4KImZ1bGwiKSwgIiVVIiBmb3IgYSBiYXNlMzIgZW5jb2RlZCBoYXNoIG9mIHRo
+ZSB1c2VyIElELAphbmQgIiUlIiBmb3IgYW4gYWN0dWFsIHBlcmNlbnQgc2lnbi4g
+SWYgbmVpdGhlciAlaSBvciAlSSBhcmUgcHJlc2VudCwKdGhlbiB0aGUgcGhvdG8g
+d2lsbCBiZSBzdXBwbGllZCB0byB0aGUgdmlld2VyIG9uIHN0YW5kYXJkIGlucHV0
+LgoKVGhlIGRlZmF1bHQgdmlld2VyIGlzICJ4bG9hZGltYWdlIC1mb3JrIC1xdWll
+dCAtdGl0bGUgJ0tleUlEIDB4JWsnClNURElOIi4gTm90ZSB0aGF0IGlmIHlvdXIg
+aW1hZ2Ugdmlld2VyIHByb2dyYW0gaXMgbm90IHNlY3VyZSwgdGhlbgpleGVjdXRp
+bmcgaXQgZnJvbSBHbnVQRyBkb2VzIG5vdCBtYWtlIGl0IHNlY3VyZS4KCkBpdGVt
+IC0tZXhlYy1wYXRoIEBjb2Rle3N0cmluZ30KQG9waW5kZXggZXhlYy1wYXRoClNl
+dHMgYSBsaXN0IG9mIGRpcmVjdG9yaWVzIHRvIHNlYXJjaCBmb3IgcGhvdG8gdmll
+d2VycyBhbmQga2V5c2VydmVyCmhlbHBlcnMuIElmIG5vdCBwcm92aWRlZCwga2V5
+c2VydmVyIGhlbHBlcnMgdXNlIHRoZSBjb21waWxlZC1pbgpkZWZhdWx0IGRpcmVj
+dG9yeSwgYW5kIHBob3RvIHZpZXdlcnMgdXNlIHRoZSAkUEFUSCBlbnZpcm9ubWVu
+dAp2YXJpYWJsZS4KTm90ZSwgdGhhdCBvbiBXMzIgc3lzdGVtIHRoaXMgdmFsdWUg
+aXMgaWdub3JlZCB3aGVuIHNlYXJjaGluZyBmb3IKa2V5c2VydmVyIGhlbHBlcnMu
+CgpAaXRlbSAtLWtleXJpbmcgQGNvZGV7ZmlsZX0KQG9waW5kZXgga2V5cmluZwpB
+ZGQgQGNvZGV7ZmlsZX0gdG8gdGhlIGN1cnJlbnQgbGlzdCBvZiBrZXlyaW5ncy4g
+SWYgQGNvZGV7ZmlsZX0gYmVnaW5zCndpdGggYSB0aWxkZSBhbmQgYSBzbGFzaCwg
+dGhlc2UgYXJlIHJlcGxhY2VkIGJ5IHRoZSAkSE9NRSBkaXJlY3RvcnkuIElmCnRo
+ZSBmaWxlbmFtZSBkb2VzIG5vdCBjb250YWluIGEgc2xhc2gsIGl0IGlzIGFzc3Vt
+ZWQgdG8gYmUgaW4gdGhlIEdudVBHCmhvbWUgZGlyZWN0b3J5ICgifi8uZ251cGci
+IGlmIEBvcHRpb257LS1ob21lZGlyfSBvciAkR05VUEdIT01FIGlzIG5vdAp1c2Vk
+KS4KCk5vdGUgdGhhdCB0aGlzIGFkZHMgYSBrZXlyaW5nIHRvIHRoZSBjdXJyZW50
+IGxpc3QuIElmIHRoZSBpbnRlbnQgaXMgdG8KdXNlIHRoZSBzcGVjaWZpZWQga2V5
+cmluZyBhbG9uZSwgdXNlIEBvcHRpb257LS1rZXlyaW5nfSBhbG9uZyB3aXRoCkBv
+cHRpb257LS1uby1kZWZhdWx0LWtleXJpbmd9LgoKQGl0ZW0gLS1zZWNyZXQta2V5
+cmluZyBAY29kZXtmaWxlfQpAb3BpbmRleCBzZWNyZXQta2V5cmluZwpUaGlzIGlz
+IGFuIG9ic29sZXRlIG9wdGlvbiBhbmQgaWdub3JlZC4gIEFsbCBzZWNyZXQga2V5
+cyBhcmUgc3RvcmVkIGluCnRoZSBAZmlsZXtwcml2YXRlLWtleXMtdjEuZH0gZGly
+ZWN0b3J5IGJlbG93IHRoZSBHbnVQRyBob21lIGRpcmVjdG9yeS4KCkBpdGVtIC0t
+cHJpbWFyeS1rZXlyaW5nIEBjb2Rle2ZpbGV9CkBvcGluZGV4IHByaW1hcnkta2V5
+cmluZwpEZXNpZ25hdGUgQGNvZGV7ZmlsZX0gYXMgdGhlIHByaW1hcnkgcHVibGlj
+IGtleXJpbmcuIFRoaXMgbWVhbnMgdGhhdApuZXdseSBpbXBvcnRlZCBrZXlzICh2
+aWEgQG9wdGlvbnstLWltcG9ydH0gb3Iga2V5c2VydmVyCkBvcHRpb257LS1yZWN2
+LWZyb219KSB3aWxsIGdvIHRvIHRoaXMga2V5cmluZy4KCkBpdGVtIC0tdHJ1c3Rk
+Yi1uYW1lIEBjb2Rle2ZpbGV9CkBvcGluZGV4IHRydXN0ZGItbmFtZQpVc2UgQGNv
+ZGV7ZmlsZX0gaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCB0cnVzdGRiLiBJZiBAY29k
+ZXtmaWxlfSBiZWdpbnMKd2l0aCBhIHRpbGRlIGFuZCBhIHNsYXNoLCB0aGVzZSBh
+cmUgcmVwbGFjZWQgYnkgdGhlICRIT01FIGRpcmVjdG9yeS4gSWYKdGhlIGZpbGVu
+YW1lIGRvZXMgbm90IGNvbnRhaW4gYSBzbGFzaCwgaXQgaXMgYXNzdW1lZCB0byBi
+ZSBpbiB0aGUgR251UEcKaG9tZSBkaXJlY3RvcnkgKEBmaWxle34vLmdudXBnfSBp
+ZiBAb3B0aW9uey0taG9tZWRpcn0gb3IgJEdOVVBHSE9NRSBpcwpub3QgdXNlZCku
+CgpAaW5jbHVkZSBvcHQtaG9tZWRpci50ZXhpCgoKQGl0ZW0gLS1kaXNwbGF5LWNo
+YXJzZXQgQGNvZGV7bmFtZX0KQG9waW5kZXggZGlzcGxheS1jaGFyc2V0ClNldCB0
+aGUgbmFtZSBvZiB0aGUgbmF0aXZlIGNoYXJhY3RlciBzZXQuIFRoaXMgaXMgdXNl
+ZCB0byBjb252ZXJ0CnNvbWUgaW5mb3JtYXRpb25hbCBzdHJpbmdzIGxpa2UgdXNl
+ciBJRHMgdG8gdGhlIHByb3BlciBVVEYtOCBlbmNvZGluZy4KTm90ZSB0aGF0IHRo
+aXMgaGFzIG5vdGhpbmcgdG8gZG8gd2l0aCB0aGUgY2hhcmFjdGVyIHNldCBvZiBk
+YXRhIHRvIGJlCmVuY3J5cHRlZCBvciBzaWduZWQ7IEdudVBHIGRvZXMgbm90IHJl
+Y29kZSB1c2VyLXN1cHBsaWVkIGRhdGEuIElmCnRoaXMgb3B0aW9uIGlzIG5vdCB1
+c2VkLCB0aGUgZGVmYXVsdCBjaGFyYWN0ZXIgc2V0IGlzIGRldGVybWluZWQgZnJv
+bQp0aGUgY3VycmVudCBsb2NhbGUuIEEgdmVyYm9zaXR5IGxldmVsIG9mIDMgc2hv
+d3MgdGhlIGNob3NlbiBzZXQuClZhbGlkIHZhbHVlcyBmb3IgQGNvZGV7bmFtZX0g
+YXJlOgoKQHRhYmxlIEBhc2lzCgogIEBpdGVtIGlzby04ODU5LTEKICBAb3BpbmRl
+eCBkaXNwbGF5LWNoYXJzZXQ6aXNvLTg4NTktMQogIFRoaXMgaXMgdGhlIExhdGlu
+IDEgc2V0LgoKICBAaXRlbSBpc28tODg1OS0yCiAgQG9waW5kZXggZGlzcGxheS1j
+aGFyc2V0Omlzby04ODU5LTIKICBUaGUgTGF0aW4gMiBzZXQuCgogIEBpdGVtIGlz
+by04ODU5LTE1CiAgQG9waW5kZXggZGlzcGxheS1jaGFyc2V0Omlzby04ODU5LTE1
+CiAgVGhpcyBpcyBjdXJyZW50bHkgYW4gYWxpYXMgZm9yCiAgdGhlIExhdGluIDEg
+c2V0LgoKICBAaXRlbSBrb2k4LXIKICBAb3BpbmRleCBkaXNwbGF5LWNoYXJzZXQ6
+a29pOC1yCiAgVGhlIHVzdWFsIFJ1c3NpYW4gc2V0IChyZmMxNDg5KS4KCiAgQGl0
+ZW0gdXRmLTgKICBAb3BpbmRleCBkaXNwbGF5LWNoYXJzZXQ6dXRmLTgKICBCeXBh
+c3MgYWxsIHRyYW5zbGF0aW9ucyBhbmQgYXNzdW1lCiAgdGhhdCB0aGUgT1MgdXNl
+cyBuYXRpdmUgVVRGLTggZW5jb2RpbmcuCkBlbmQgdGFibGUKCkBpdGVtIC0tdXRm
+OC1zdHJpbmdzCkBpdGVteCAtLW5vLXV0Zjgtc3RyaW5ncwpAb3BpbmRleCB1dGY4
+LXN0cmluZ3MKQXNzdW1lIHRoYXQgY29tbWFuZCBsaW5lIGFyZ3VtZW50cyBhcmUg
+Z2l2ZW4gYXMgVVRGOCBzdHJpbmdzLiBUaGUKZGVmYXVsdCAoQG9wdGlvbnstLW5v
+LXV0Zjgtc3RyaW5nc30pIGlzIHRvIGFzc3VtZSB0aGF0IGFyZ3VtZW50cyBhcmUK
+ZW5jb2RlZCBpbiB0aGUgY2hhcmFjdGVyIHNldCBhcyBzcGVjaWZpZWQgYnkKQG9w
+dGlvbnstLWRpc3BsYXktY2hhcnNldH0uIFRoZXNlIG9wdGlvbnMgYWZmZWN0IGFs
+bCBmb2xsb3dpbmcKYXJndW1lbnRzLiBCb3RoIG9wdGlvbnMgbWF5IGJlIHVzZWQg
+bXVsdGlwbGUgdGltZXMuCgpAYW5jaG9ye2dwZy1vcHRpb24gLS1vcHRpb25zfQpA
+aXRlbSAtLW9wdGlvbnMgQGNvZGV7ZmlsZX0KQG9waW5kZXggb3B0aW9ucwpSZWFk
+IG9wdGlvbnMgZnJvbSBAY29kZXtmaWxlfSBhbmQgZG8gbm90IHRyeSB0byByZWFk
+IHRoZW0gZnJvbSB0aGUKZGVmYXVsdCBvcHRpb25zIGZpbGUgaW4gdGhlIGhvbWVk
+aXIgKHNlZSBAb3B0aW9uey0taG9tZWRpcn0pLiBUaGlzCm9wdGlvbiBpcyBpZ25v
+cmVkIGlmIHVzZWQgaW4gYW4gb3B0aW9ucyBmaWxlLgoKQGl0ZW0gLS1uby1vcHRp
+b25zCkBvcGluZGV4IG5vLW9wdGlvbnMKU2hvcnRjdXQgZm9yIEBvcHRpb257LS1v
+cHRpb25zIC9kZXYvbnVsbH0uIFRoaXMgb3B0aW9uIGlzIGRldGVjdGVkCmJlZm9y
+ZSBhbiBhdHRlbXB0IHRvIG9wZW4gYW4gb3B0aW9uIGZpbGUuICBVc2luZyB0aGlz
+IG9wdGlvbiB3aWxsIGFsc28KcHJldmVudCB0aGUgY3JlYXRpb24gb2YgYSBAZmls
+ZXt+Ly5nbnVwZ30gaG9tZWRpci4KCkBpdGVtIC16IEBjb2Rle259CkBpdGVteCAt
+LWNvbXByZXNzLWxldmVsIEBjb2Rle259CkBpdGVteCAtLWJ6aXAyLWNvbXByZXNz
+LWxldmVsIEBjb2Rle259CkBvcGluZGV4IGNvbXByZXNzLWxldmVsCkBvcGluZGV4
+IGJ6aXAyLWNvbXByZXNzLWxldmVsClNldCBjb21wcmVzc2lvbiBsZXZlbCB0byBA
+Y29kZXtufSBmb3IgdGhlIFpJUCBhbmQgWkxJQiBjb21wcmVzc2lvbgphbGdvcml0
+aG1zLiBUaGUgZGVmYXVsdCBpcyB0byB1c2UgdGhlIGRlZmF1bHQgY29tcHJlc3Np
+b24gbGV2ZWwgb2YgemxpYgoobm9ybWFsbHkgNikuIEBvcHRpb257LS1iemlwMi1j
+b21wcmVzcy1sZXZlbH0gc2V0cyB0aGUgY29tcHJlc3Npb24gbGV2ZWwKZm9yIHRo
+ZSBCWklQMiBjb21wcmVzc2lvbiBhbGdvcml0aG0gKGRlZmF1bHRpbmcgdG8gNiBh
+cyB3ZWxsKS4gVGhpcyBpcyBhCmRpZmZlcmVudCBvcHRpb24gZnJvbSBAb3B0aW9u
+ey0tY29tcHJlc3MtbGV2ZWx9IHNpbmNlIEJaSVAyIHVzZXMgYQpzaWduaWZpY2Fu
+dCBhbW91bnQgb2YgbWVtb3J5IGZvciBlYWNoIGFkZGl0aW9uYWwgY29tcHJlc3Np
+b24gbGV2ZWwuCkBvcHRpb257LXp9IHNldHMgYm90aC4gQSB2YWx1ZSBvZiAwIGZv
+ciBAY29kZXtufSBkaXNhYmxlcyBjb21wcmVzc2lvbi4KCkBpdGVtIC0tYnppcDIt
+ZGVjb21wcmVzcy1sb3dtZW0KQG9waW5kZXggYnppcDItZGVjb21wcmVzcy1sb3dt
+ZW0KVXNlIGEgZGlmZmVyZW50IGRlY29tcHJlc3Npb24gbWV0aG9kIGZvciBCWklQ
+MiBjb21wcmVzc2VkIGZpbGVzLiBUaGlzCmFsdGVybmF0ZSBtZXRob2QgdXNlcyBh
+IGJpdCBtb3JlIHRoYW4gaGFsZiB0aGUgbWVtb3J5LCBidXQgYWxzbyBydW5zCmF0
+IGhhbGYgdGhlIHNwZWVkLiBUaGlzIGlzIHVzZWZ1bCB1bmRlciBleHRyZW1lIGxv
+dyBtZW1vcnkKY2lyY3Vtc3RhbmNlcyB3aGVuIHRoZSBmaWxlIHdhcyBvcmlnaW5h
+bGx5IGNvbXByZXNzZWQgYXQgYSBoaWdoCkBvcHRpb257LS1iemlwMi1jb21wcmVz
+cy1sZXZlbH0uCgoKQGl0ZW0gLS1tYW5nbGUtZG9zLWZpbGVuYW1lcwpAaXRlbXgg
+LS1uby1tYW5nbGUtZG9zLWZpbGVuYW1lcwpAb3BpbmRleCBtYW5nbGUtZG9zLWZp
+bGVuYW1lcwpAb3BpbmRleCBuby1tYW5nbGUtZG9zLWZpbGVuYW1lcwpPbGRlciB2
+ZXJzaW9uIG9mIFdpbmRvd3MgY2Fubm90IGhhbmRsZSBmaWxlbmFtZXMgd2l0aCBt
+b3JlIHRoYW4gb25lCmRvdC4gQG9wdGlvbnstLW1hbmdsZS1kb3MtZmlsZW5hbWVz
+fSBjYXVzZXMgR251UEcgdG8gcmVwbGFjZSAocmF0aGVyCnRoYW4gYWRkIHRvKSB0
+aGUgZXh0ZW5zaW9uIG9mIGFuIG91dHB1dCBmaWxlbmFtZSB0byBhdm9pZCB0aGlz
+CnByb2JsZW0uIFRoaXMgb3B0aW9uIGlzIG9mZiBieSBkZWZhdWx0IGFuZCBoYXMg
+bm8gZWZmZWN0IG9uIG5vbi1XaW5kb3dzCnBsYXRmb3Jtcy4KCkBpdGVtIC0tYXNr
+LWNlcnQtbGV2ZWwKQGl0ZW14IC0tbm8tYXNrLWNlcnQtbGV2ZWwKQG9waW5kZXgg
+YXNrLWNlcnQtbGV2ZWwKV2hlbiBtYWtpbmcgYSBrZXkgc2lnbmF0dXJlLCBwcm9t
+cHQgZm9yIGEgY2VydGlmaWNhdGlvbiBsZXZlbC4gSWYgdGhpcwpvcHRpb24gaXMg
+bm90IHNwZWNpZmllZCwgdGhlIGNlcnRpZmljYXRpb24gbGV2ZWwgdXNlZCBpcyBz
+ZXQgdmlhCkBvcHRpb257LS1kZWZhdWx0LWNlcnQtbGV2ZWx9LiBTZWUgQG9wdGlv
+bnstLWRlZmF1bHQtY2VydC1sZXZlbH0gZm9yCmluZm9ybWF0aW9uIG9uIHRoZSBz
+cGVjaWZpYyBsZXZlbHMgYW5kIGhvdyB0aGV5IGFyZQp1c2VkLiBAb3B0aW9uey0t
+bm8tYXNrLWNlcnQtbGV2ZWx9IGRpc2FibGVzIHRoaXMgb3B0aW9uLiBUaGlzIG9w
+dGlvbgpkZWZhdWx0cyB0byBuby4KCkBpdGVtIC0tZGVmYXVsdC1jZXJ0LWxldmVs
+IEBjb2Rle259CkBvcGluZGV4IGRlZmF1bHQtY2VydC1sZXZlbApUaGUgZGVmYXVs
+dCB0byB1c2UgZm9yIHRoZSBjaGVjayBsZXZlbCB3aGVuIHNpZ25pbmcgYSBrZXku
+CgowIG1lYW5zIHlvdSBtYWtlIG5vIHBhcnRpY3VsYXIgY2xhaW0gYXMgdG8gaG93
+IGNhcmVmdWxseSB5b3UgdmVyaWZpZWQKdGhlIGtleS4KCjEgbWVhbnMgeW91IGJl
+bGlldmUgdGhlIGtleSBpcyBvd25lZCBieSB0aGUgcGVyc29uIHdobyBjbGFpbXMg
+dG8gb3duCml0IGJ1dCB5b3UgY291bGQgbm90LCBvciBkaWQgbm90IHZlcmlmeSB0
+aGUga2V5IGF0IGFsbC4gVGhpcyBpcwp1c2VmdWwgZm9yIGEgInBlcnNvbmEiIHZl
+cmlmaWNhdGlvbiwgd2hlcmUgeW91IHNpZ24gdGhlIGtleSBvZiBhCnBzZXVkb255
+bW91cyB1c2VyLgoKMiBtZWFucyB5b3UgZGlkIGNhc3VhbCB2ZXJpZmljYXRpb24g
+b2YgdGhlIGtleS4gRm9yIGV4YW1wbGUsIHRoaXMKY291bGQgbWVhbiB0aGF0IHlv
+dSB2ZXJpZmllZCB0aGUga2V5IGZpbmdlcnByaW50IGFuZCBjaGVja2VkIHRoZQp1
+c2VyIElEIG9uIHRoZSBrZXkgYWdhaW5zdCBhIHBob3RvIElELgoKMyBtZWFucyB5
+b3UgZGlkIGV4dGVuc2l2ZSB2ZXJpZmljYXRpb24gb2YgdGhlIGtleS4gRm9yIGV4
+YW1wbGUsIHRoaXMKY291bGQgbWVhbiB0aGF0IHlvdSB2ZXJpZmllZCB0aGUga2V5
+IGZpbmdlcnByaW50IHdpdGggdGhlIG93bmVyIG9mIHRoZQprZXkgaW4gcGVyc29u
+LCBhbmQgdGhhdCB5b3UgY2hlY2tlZCwgYnkgbWVhbnMgb2YgYSBoYXJkIHRvIGZv
+cmdlCmRvY3VtZW50IHdpdGggYSBwaG90byBJRCAoc3VjaCBhcyBhIHBhc3Nwb3J0
+KSB0aGF0IHRoZSBuYW1lIG9mIHRoZSBrZXkKb3duZXIgbWF0Y2hlcyB0aGUgbmFt
+ZSBpbiB0aGUgdXNlciBJRCBvbiB0aGUga2V5LCBhbmQgZmluYWxseSB0aGF0IHlv
+dQp2ZXJpZmllZCAoYnkgZXhjaGFuZ2Ugb2YgZW1haWwpIHRoYXQgdGhlIGVtYWls
+IGFkZHJlc3Mgb24gdGhlIGtleQpiZWxvbmdzIHRvIHRoZSBrZXkgb3duZXIuCgpO
+b3RlIHRoYXQgdGhlIGV4YW1wbGVzIGdpdmVuIGFib3ZlIGZvciBsZXZlbHMgMiBh
+bmQgMyBhcmUganVzdCB0aGF0OgpleGFtcGxlcy4gSW4gdGhlIGVuZCwgaXQgaXMg
+dXAgdG8geW91IHRvIGRlY2lkZSBqdXN0IHdoYXQgImNhc3VhbCIKYW5kICJleHRl
+bnNpdmUiIG1lYW4gdG8geW91LgoKVGhpcyBvcHRpb24gZGVmYXVsdHMgdG8gMCAo
+bm8gcGFydGljdWxhciBjbGFpbSkuCgpAaXRlbSAtLW1pbi1jZXJ0LWxldmVsCkBv
+cGluZGV4IG1pbi1jZXJ0LWxldmVsCldoZW4gYnVpbGRpbmcgdGhlIHRydXN0IGRh
+dGFiYXNlLCB0cmVhdCBhbnkgc2lnbmF0dXJlcyB3aXRoIGEKY2VydGlmaWNhdGlv
+biBsZXZlbCBiZWxvdyB0aGlzIGFzIGludmFsaWQuIERlZmF1bHRzIHRvIDIsIHdo
+aWNoCmRpc3JlZ2FyZHMgbGV2ZWwgMSBzaWduYXR1cmVzLiBOb3RlIHRoYXQgbGV2
+ZWwgMCAibm8gcGFydGljdWxhcgpjbGFpbSIgc2lnbmF0dXJlcyBhcmUgYWx3YXlz
+IGFjY2VwdGVkLgoKQGl0ZW0gLS10cnVzdGVkLWtleSBAY29kZXtsb25nIGtleSBJ
+RH0KQG9waW5kZXggdHJ1c3RlZC1rZXkKQXNzdW1lIHRoYXQgdGhlIHNwZWNpZmll
+ZCBrZXkgKHdoaWNoIG11c3QgYmUgZ2l2ZW4KYXMgYSBmdWxsIDggYnl0ZSBrZXkg
+SUQpIGlzIGFzIHRydXN0d29ydGh5IGFzIG9uZSBvZgp5b3VyIG93biBzZWNyZXQg
+a2V5cy4gVGhpcyBvcHRpb24gaXMgdXNlZnVsIGlmIHlvdQpkb24ndCB3YW50IHRv
+IGtlZXAgeW91ciBzZWNyZXQga2V5cyAob3Igb25lIG9mIHRoZW0pCm9ubGluZSBi
+dXQgc3RpbGwgd2FudCB0byBiZSBhYmxlIHRvIGNoZWNrIHRoZSB2YWxpZGl0eSBv
+ZiBhIGdpdmVuCnJlY2lwaWVudCdzIG9yIHNpZ25hdG9yJ3Mga2V5LgoKQGl0ZW0g
+LS10cnVzdC1tb2RlbCBAY29kZXtwZ3B8Y2xhc3NpY3x0b2Z1fHRvZnUrcGdwfGRp
+cmVjdHxhbHdheXN8YXV0b30KQG9waW5kZXggdHJ1c3QtbW9kZWwKU2V0IHdoYXQg
+dHJ1c3QgbW9kZWwgR251UEcgc2hvdWxkIGZvbGxvdy4gVGhlIG1vZGVscyBhcmU6
+CgpAdGFibGUgQGFzaXMKCiAgQGl0ZW0gcGdwCiAgQG9waW5kZXggdHJ1c3QtbW9k
+ZTpwZ3AKICBUaGlzIGlzIHRoZSBXZWIgb2YgVHJ1c3QgY29tYmluZWQgd2l0aCB0
+cnVzdCBzaWduYXR1cmVzIGFzIHVzZWQgaW4gUEdQCiAgNS54IGFuZCBsYXRlci4g
+VGhpcyBpcyB0aGUgZGVmYXVsdCB0cnVzdCBtb2RlbCB3aGVuIGNyZWF0aW5nIGEg
+bmV3CiAgdHJ1c3QgZGF0YWJhc2UuCgogIEBpdGVtIGNsYXNzaWMKICBAb3BpbmRl
+eCB0cnVzdC1tb2RlOmNsYXNzaWMKICBUaGlzIGlzIHRoZSBzdGFuZGFyZCBXZWIg
+b2YgVHJ1c3QgYXMgaW50cm9kdWNlZCBieSBQR1AgMi4KCiAgQGl0ZW0gdG9mdQog
+IEBvcGluZGV4IHRydXN0LW1vZGU6dG9mdQogIEBhbmNob3J7dHJ1c3QtbW9kZWwt
+dG9mdX0KICBUT0ZVIHN0YW5kcyBmb3IgVHJ1c3QgT24gRmlyc3QgVXNlLiAgSW4g
+dGhpcyB0cnVzdCBtb2RlbCwgdGhlIGZpcnN0CiAgdGltZSBhIGtleSBpcyBzZWVu
+LCBpdCBpcyBtZW1vcml6ZWQuICBJZiBsYXRlciBhbm90aGVyIGtleSBpcyBzZWVu
+CiAgd2l0aCBhIHVzZXIgaWQgd2l0aCB0aGUgc2FtZSBlbWFpbCBhZGRyZXNzLCBh
+IHdhcm5pbmcgaXMgZGlzcGxheWVkCiAgaW5kaWNhdGluZyB0aGF0IHRoZXJlIGlz
+IGEgY29uZmxpY3QgYW5kIHRoYXQgdGhlIGtleSBtaWdodCBiZSBhCiAgZm9yZ2Vy
+eSBhbmQgYW4gYXR0ZW1wdCBhdCBhIG1hbi1pbi10aGUtbWlkZGxlIGF0dGFjay4K
+CiAgQmVjYXVzZSBhIHBvdGVudGlhbCBhdHRhY2tlciBpcyBhYmxlIHRvIGNvbnRy
+b2wgdGhlIGVtYWlsIGFkZHJlc3MKICBhbmQgdGhlcmVieSBjaXJjdW12ZW50IHRo
+ZSBjb25mbGljdCBkZXRlY3Rpb24gYWxnb3JpdGhtIGJ5IHVzaW5nIGFuCiAgZW1h
+aWwgYWRkcmVzcyB0aGF0IGlzIHNpbWlsYXIgaW4gYXBwZWFyYW5jZSB0byBhIHRy
+dXN0ZWQgZW1haWwKICBhZGRyZXNzLCB3aGVuZXZlciBhIG1lc3NhZ2UgaXMgdmVy
+aWZpZWQsIHN0YXRpc3RpY3MgYWJvdXQgdGhlIG51bWJlcgogIG9mIG1lc3NhZ2Vz
+IHNpZ25lZCB3aXRoIHRoZSBrZXkgYXJlIHNob3duLiAgSW4gdGhpcyB3YXksIGEg
+dXNlciBjYW4KICBlYXNpbHkgaWRlbnRpZnkgYXR0YWNrcyB1c2luZyBmYWtlIGtl
+eXMgZm9yIHJlZ3VsYXIgY29ycmVzcG9uZGVudHMuCgogIFdoZW4gY29tcGFyZWQg
+d2l0aCB0aGUgV2ViIG9mIFRydXN0LCBUT0ZVIG9mZmVycyBzaWduaWZpY2FudGx5
+CiAgd2Vha2VyIHNlY3VyaXR5IGd1YXJhbnRlZXMuICBJbiBwYXJ0aWN1bGFyLCBU
+T0ZVIG9ubHkgaGVscHMgZW5zdXJlCiAgY29uc2lzdGVuY3kgKHRoYXQgaXMsIHRo
+YXQgdGhlIGJpbmRpbmcgYmV0d2VlbiBhIGtleSBhbmQgZW1haWwKICBhZGRyZXNz
+IGRvZXNuJ3QgY2hhbmdlKS4gIEEgbWFqb3IgYWR2YW50YWdlIG9mIFRPRlUgaXMg
+dGhhdCBpdAogIHJlcXVpcmVzIGxpdHRsZSBtYWludGVuYW5jZSB0byB1c2UgY29y
+cmVjdGx5LiAgVG8gdXNlIHRoZSB3ZWIgb2YKICB0cnVzdCBwcm9wZXJseSwgeW91
+IG5lZWQgdG8gYWN0aXZlbHkgc2lnbiBrZXlzIGFuZCBtYXJrIHVzZXJzIGFzCiAg
+dHJ1c3RlZCBpbnRyb2R1Y2Vycy4gIFRoaXMgaXMgYSB0aW1lLWNvbnN1bWluZyBw
+cm9jZXNzIGFuZCBhbmVjZG90YWwKICBldmlkZW5jZSBzdWdnZXN0cyB0aGF0IGV2
+ZW4gc2VjdXJpdHktY29uc2Npb3VzIHVzZXJzIHJhcmVseSB0YWtlIHRoZQogIHRp
+bWUgdG8gZG8gdGhpcyB0aG9yb3VnaGx5IGFuZCBpbnN0ZWFkIHJlbHkgb24gYW4g
+YWQtaG9jIFRPRlUKICBwcm9jZXNzLgoKICBJbiB0aGUgVE9GVSBtb2RlbCwgcG9s
+aWNpZXMgYXJlIGFzc29jaWF0ZWQgd2l0aCBiaW5kaW5ncyBiZXR3ZWVuCiAga2V5
+cyBhbmQgZW1haWwgYWRkcmVzc2VzICh3aGljaCBhcmUgZXh0cmFjdGVkIGZyb20g
+dXNlciBpZHMgYW5kCiAgbm9ybWFsaXplZCkuICBUaGVyZSBhcmUgZml2ZSBwb2xp
+Y2llcywgd2hpY2ggY2FuIGJlIHNldCBtYW51YWxseQogIHVzaW5nIHRoZSBAb3B0
+aW9uey0tdG9mdS1wb2xpY3l9IG9wdGlvbi4gIFRoZSBkZWZhdWx0IHBvbGljeSBj
+YW4gYmUKICBzZXQgdXNpbmcgdGhlIEBvcHRpb257LS10b2Z1LWRlZmF1bHQtcG9s
+aWN5fSBwb2xpY3kuCgogIFRoZSBUT0ZVIHBvbGljaWVzIGFyZTogQGNvZGV7YXV0
+b30sIEBjb2Rle2dvb2R9LCBAY29kZXt1bmtub3dufSwKICBAY29kZXtiYWR9IGFu
+ZCBAY29kZXthc2t9LiAgVGhlIEBjb2Rle2F1dG99IHBvbGljeSBpcyB1c2VkIGJ5
+CiAgZGVmYXVsdCAodW5sZXNzIG92ZXJyaWRkZW4gYnkgQG9wdGlvbnstLXRvZnUt
+ZGVmYXVsdC1wb2xpY3l9KSBhbmQKICBtYXJrcyBhIGJpbmRpbmcgYXMgbWFyZ2lu
+YWxseSB0cnVzdGVkLiAgVGhlIEBjb2Rle2dvb2R9LAogIEBjb2Rle3Vua25vd259
+IGFuZCBAY29kZXtiYWR9IHBvbGljaWVzIG1hcmsgYSBiaW5kaW5nIGFzIGZ1bGx5
+CiAgdHJ1c3RlZCwgYXMgaGF2aW5nIHVua25vd24gdHJ1c3Qgb3IgYXMgaGF2aW5n
+IHRydXN0IG5ldmVyLAogIHJlc3BlY3RpdmVseS4gIFRoZSBAY29kZXt1bmtub3du
+fSBwb2xpY3kgaXMgdXNlZnVsIGZvciBqdXN0IHVzaW5nCiAgVE9GVSB0byBkZXRl
+Y3QgY29uZmxpY3RzLCBidXQgdG8gbmV2ZXIgYXNzaWduIHBvc2l0aXZlIHRydXN0
+IHRvIGEKICBiaW5kaW5nLiAgVGhlIGZpbmFsIHBvbGljeSwgQGNvZGV7YXNrfSBw
+cm9tcHRzIHRoZSB1c2VyIHRvIGluZGljYXRlCiAgdGhlIGJpbmRpbmcncyB0cnVz
+dC4gIElmIGJhdGNoIG1vZGUgaXMgZW5hYmxlZCAob3IgaW5wdXQgaXMKICBpbmFw
+cHJvcHJpYXRlIGluIHRoZSBjb250ZXh0KSwgdGhlbiB0aGUgdXNlciBpcyBub3Qg
+cHJvbXB0ZWQgYW5kIHRoZQogIEBjb2Rle3VuZGVmaW5lZH0gdHJ1c3QgbGV2ZWwg
+aXMgcmV0dXJuZWQuCgogIEBpdGVtIHRvZnUrcGdwCiAgQG9waW5kZXggdHJ1c3Qt
+bW9kZTp0b2Z1K3BncAogIFRoaXMgdHJ1c3QgbW9kZWwgY29tYmluZXMgVE9GVSB3
+aXRoIHRoZSBXZWIgb2YgVHJ1c3QuICBUaGlzIGlzIGRvbmUKICBieSBjb21wdXRp
+bmcgdGhlIHRydXN0IGxldmVsIGZvciBlYWNoIG1vZGVsIGFuZCB0aGVuIHRha2lu
+ZyB0aGUKICBtYXhpbXVtIHRydXN0IGxldmVsIHdoZXJlIHRoZSB0cnVzdCBsZXZl
+bHMgYXJlIG9yZGVyZWQgYXMgZm9sbG93czoKICBAY29kZXt1bmtub3duIDwgdW5k
+ZWZpbmVkIDwgbWFyZ2luYWwgPCBmdWxseSA8IHVsdGltYXRlIDwgZXhwaXJlZCA8
+CiAgbmV2ZXJ9LgoKICBCeSBzZXR0aW5nIEBvcHRpb257LS10b2Z1LWRlZmF1bHQt
+cG9saWN5PXVua25vd259LCB0aGlzIG1vZGVsIGNhbiBiZQogIHVzZWQgdG8gaW1w
+bGVtZW50IHRoZSB3ZWIgb2YgdHJ1c3Qgd2l0aCBUT0ZVJ3MgY29uZmxpY3QgZGV0
+ZWN0aW9uCiAgYWxnb3JpdGhtLCBidXQgd2l0aG91dCBpdHMgYXNzaWdubWVudCBv
+ZiBwb3NpdGl2ZSB0cnVzdCB2YWx1ZXMsCiAgd2hpY2ggc29tZSBzZWN1cml0eS1j
+b25zY2lvdXMgdXNlcnMgZG9uJ3QgbGlrZS4KCiAgQGl0ZW0gZGlyZWN0CiAgQG9w
+aW5kZXggdHJ1c3QtbW9kZTpkaXJlY3QKICBLZXkgdmFsaWRpdHkgaXMgc2V0IGRp
+cmVjdGx5IGJ5IHRoZSB1c2VyIGFuZCBub3QgY2FsY3VsYXRlZCB2aWEgdGhlCiAg
+V2ViIG9mIFRydXN0LgoKICBAaXRlbSBhbHdheXMKICBAb3BpbmRleCB0cnVzdC1t
+b2RlOmFsd2F5cwogIFNraXAga2V5IHZhbGlkYXRpb24gYW5kIGFzc3VtZSB0aGF0
+IHVzZWQga2V5cyBhcmUgYWx3YXlzIGZ1bGx5CiAgdmFsaWQuIFlvdSBnZW5lcmFs
+bHkgd29uJ3QgdXNlIHRoaXMgdW5sZXNzIHlvdSBhcmUgdXNpbmcgc29tZQogIGV4
+dGVybmFsIHZhbGlkYXRpb24gc2NoZW1lLiBUaGlzIG9wdGlvbiBhbHNvIHN1cHBy
+ZXNzZXMgdGhlCiAgIlt1bmNlcnRhaW5dIiB0YWcgcHJpbnRlZCB3aXRoIHNpZ25h
+dHVyZSBjaGVja3Mgd2hlbiB0aGVyZSBpcyBubwogIGV2aWRlbmNlIHRoYXQgdGhl
+IHVzZXIgSUQgaXMgYm91bmQgdG8gdGhlIGtleS4gIE5vdGUgdGhhdCB0aGlzCiAg
+dHJ1c3QgbW9kZWwgc3RpbGwgZG9lcyBub3QgYWxsb3cgdGhlIHVzZSBvZiBleHBp
+cmVkLCByZXZva2VkLCBvcgogIGRpc2FibGVkIGtleXMuCgogIEBpdGVtIGF1dG8K
+ICBAb3BpbmRleCB0cnVzdC1tb2RlOmF1dG8KICBTZWxlY3QgdGhlIHRydXN0IG1v
+ZGVsIGRlcGVuZGluZyBvbiB3aGF0ZXZlciB0aGUgaW50ZXJuYWwgdHJ1c3QKICBk
+YXRhYmFzZSBzYXlzLiBUaGlzIGlzIHRoZSBkZWZhdWx0IG1vZGVsIGlmIHN1Y2gg
+YSBkYXRhYmFzZSBhbHJlYWR5CiAgZXhpc3RzLgpAZW5kIHRhYmxlCgpAaXRlbSAt
+LWF1dG8ta2V5LWxvY2F0ZSBAY29kZXtwYXJhbWV0ZXJzfQpAaXRlbXggLS1uby1h
+dXRvLWtleS1sb2NhdGUKQG9waW5kZXggYXV0by1rZXktbG9jYXRlCkdudVBHIGNh
+biBhdXRvbWF0aWNhbGx5IGxvY2F0ZSBhbmQgcmV0cmlldmUga2V5cyBhcyBuZWVk
+ZWQgdXNpbmcgdGhpcwpvcHRpb24uIFRoaXMgaGFwcGVucyB3aGVuIGVuY3J5cHRp
+bmcgdG8gYW4gZW1haWwgYWRkcmVzcyAoaW4gdGhlCiJ1c2VyQEBleGFtcGxlLmNv
+bSIgZm9ybSksIGFuZCB0aGVyZSBhcmUgbm8gdXNlckBAZXhhbXBsZS5jb20ga2V5
+cyBvbgp0aGUgbG9jYWwga2V5cmluZy4gIFRoaXMgb3B0aW9uIHRha2VzIGFueSBu
+dW1iZXIgb2YgdGhlIGZvbGxvd2luZwptZWNoYW5pc21zLCBpbiB0aGUgb3JkZXIg
+dGhleSBhcmUgdG8gYmUgdHJpZWQ6CgpAdGFibGUgQGFzaXMKCiAgQGl0ZW0gY2Vy
+dAogIExvY2F0ZSBhIGtleSB1c2luZyBETlMgQ0VSVCwgYXMgc3BlY2lmaWVkIGlu
+IHJmYzQzOTguCgogIEBpdGVtIHBrYQogIExvY2F0ZSBhIGtleSB1c2luZyBETlMg
+UEtBLgoKICBAaXRlbSBkYW5lCiAgTG9jYXRlIGEga2V5IHVzaW5nIERBTkUsIGFz
+IHNwZWNpZmllZAogIGluIGRyYWZ0LWlldGYtZGFuZS1vcGVucGdwa2V5LTA1LnR4
+dC4KCiAgQGl0ZW0gbGRhcAogIFVzaW5nIEROUyBTZXJ2aWNlIERpc2NvdmVyeSwg
+Y2hlY2sgdGhlIGRvbWFpbiBpbiBxdWVzdGlvbiBmb3IgYW55IExEQVAKICBrZXlz
+ZXJ2ZXJzIHRvIHVzZS4gIElmIHRoaXMgZmFpbHMsIGF0dGVtcHQgdG8gbG9jYXRl
+IHRoZSBrZXkgdXNpbmcgdGhlCiAgUEdQIFVuaXZlcnNhbCBtZXRob2Qgb2YgY2hl
+Y2tpbmcgQHNhbXB7bGRhcDovL2tleXMuKHRoZWRvbWFpbil9LgoKICBAaXRlbSBr
+ZXlzZXJ2ZXIKICBMb2NhdGUgYSBrZXkgdXNpbmcgd2hhdGV2ZXIga2V5c2VydmVy
+IGlzIGRlZmluZWQgdXNpbmcgdGhlCiAgQG9wdGlvbnstLWtleXNlcnZlcn0gb3B0
+aW9uLgoKICBAaXRlbSBrZXlzZXJ2ZXItVVJMCiAgSW4gYWRkaXRpb24sIGEga2V5
+c2VydmVyIFVSTCBhcyB1c2VkIGluIHRoZSBAb3B0aW9uey0ta2V5c2VydmVyfSBv
+cHRpb24KICBtYXkgYmUgdXNlZCBoZXJlIHRvIHF1ZXJ5IHRoYXQgcGFydGljdWxh
+ciBrZXlzZXJ2ZXIuCgogIEBpdGVtIGxvY2FsCiAgTG9jYXRlIHRoZSBrZXkgdXNp
+bmcgdGhlIGxvY2FsIGtleXJpbmdzLiAgVGhpcyBtZWNoYW5pc20gYWxsb3dzIHRv
+CiAgc2VsZWN0IHRoZSBvcmRlciBhIGxvY2FsIGtleSBsb29rdXAgaXMgZG9uZS4g
+IFRodXMgdXNpbmcKICBAc2FtcHstLWF1dG8ta2V5LWxvY2F0ZSBsb2NhbH0gaXMg
+aWRlbnRpY2FsIHRvCiAgQG9wdGlvbnstLW5vLWF1dG8ta2V5LWxvY2F0ZX0uCgog
+IEBpdGVtIG5vZGVmYXVsdAogIFRoaXMgZmxhZyBkaXNhYmxlcyB0aGUgc3RhbmRh
+cmQgbG9jYWwga2V5IGxvb2t1cCwgZG9uZSBiZWZvcmUgYW55IG9mIHRoZQogIG1l
+Y2hhbmlzbXMgZGVmaW5lZCBieSB0aGUgQG9wdGlvbnstLWF1dG8ta2V5LWxvY2F0
+ZX0gYXJlIHRyaWVkLiAgVGhlCiAgcG9zaXRpb24gb2YgdGhpcyBtZWNoYW5pc20g
+aW4gdGhlIGxpc3QgZG9lcyBub3QgbWF0dGVyLiAgSXQgaXMgbm90CiAgcmVxdWly
+ZWQgaWYgQGNvZGV7bG9jYWx9IGlzIGFsc28gdXNlZC4KCiAgQGl0ZW0gY2xlYXIK
+ICBDbGVhciBhbGwgZGVmaW5lZCBtZWNoYW5pc21zLiAgVGhpcyBpcyB1c2VmdWwg
+dG8gb3ZlcnJpZGUKICBtZWNoYW5pc21zIGdpdmVuIGluIGEgY29uZmlnIGZpbGUu
+CgpAZW5kIHRhYmxlCgpAaXRlbSAtLWtleWlkLWZvcm1hdCBAY29kZXtzaG9ydHww
+eHNob3J0fGxvbmd8MHhsb25nfQpAb3BpbmRleCBrZXlpZC1mb3JtYXQKU2VsZWN0
+IGhvdyB0byBkaXNwbGF5IGtleSBJRHMuICJzaG9ydCIgaXMgdGhlIHRyYWRpdGlv
+bmFsIDgtY2hhcmFjdGVyCmtleSBJRC4gImxvbmciIGlzIHRoZSBtb3JlIGFjY3Vy
+YXRlIChidXQgbGVzcyBjb252ZW5pZW50KQoxNi1jaGFyYWN0ZXIga2V5IElELiBB
+ZGQgYW4gIjB4IiB0byBlaXRoZXIgdG8gaW5jbHVkZSBhbiAiMHgiIGF0IHRoZQpi
+ZWdpbm5pbmcgb2YgdGhlIGtleSBJRCwgYXMgaW4gMHg5OTI0MjU2MC4gIE5vdGUg
+dGhhdCB0aGlzIG9wdGlvbiBpcwppZ25vcmVkIGlmIHRoZSBvcHRpb24gLS13aXRo
+LWNvbG9ucyBpcyB1c2VkLgoKQGl0ZW0gLS1rZXlzZXJ2ZXIgQGNvZGV7bmFtZX0K
+QG9waW5kZXgga2V5c2VydmVyClRoaXMgb3B0aW9uIGlzIGRlcHJlY2F0ZWQgLSBw
+bGVhc2UgdXNlIHRoZSBAb3B0aW9uey0ta2V5c2VydmVyfSBpbgpAZmlsZXtkaXJt
+bmdyLmNvbmZ9IGluc3RlYWQuCgpVc2UgQGNvZGV7bmFtZX0gYXMgeW91ciBrZXlz
+ZXJ2ZXIuIFRoaXMgaXMgdGhlIHNlcnZlciB0aGF0CkBvcHRpb257LS1yZWN2LWtl
+eXN9LCBAb3B0aW9uey0tc2VuZC1rZXlzfSwgYW5kIEBvcHRpb257LS1zZWFyY2gt
+a2V5c30Kd2lsbCBjb21tdW5pY2F0ZSB3aXRoIHRvIHJlY2VpdmUga2V5cyBmcm9t
+LCBzZW5kIGtleXMgdG8sIGFuZCBzZWFyY2ggZm9yCmtleXMgb24uIFRoZSBmb3Jt
+YXQgb2YgdGhlIEBjb2Rle25hbWV9IGlzIGEgVVJJOgpgc2NoZW1lOlsvL11rZXlz
+ZXJ2ZXJuYW1lWzpwb3J0XScgVGhlIHNjaGVtZSBpcyB0aGUgdHlwZSBvZiBrZXlz
+ZXJ2ZXI6CiJoa3AiIGZvciB0aGUgSFRUUCAob3IgY29tcGF0aWJsZSkga2V5c2Vy
+dmVycywgImxkYXAiIGZvciB0aGUgTERBUAprZXlzZXJ2ZXJzLCBvciAibWFpbHRv
+IiBmb3IgdGhlIEdyYWZmIGVtYWlsIGtleXNlcnZlci4gTm90ZSB0aGF0IHlvdXIK
+cGFydGljdWxhciBpbnN0YWxsYXRpb24gb2YgR251UEcgbWF5IGhhdmUgb3RoZXIg
+a2V5c2VydmVyIHR5cGVzCmF2YWlsYWJsZSBhcyB3ZWxsLiBLZXlzZXJ2ZXIgc2No
+ZW1lcyBhcmUgY2FzZS1pbnNlbnNpdGl2ZS4gQWZ0ZXIgdGhlCmtleXNlcnZlciBu
+YW1lLCBvcHRpb25hbCBrZXlzZXJ2ZXIgY29uZmlndXJhdGlvbiBvcHRpb25zIG1h
+eSBiZQpwcm92aWRlZC4gVGhlc2UgYXJlIHRoZSBzYW1lIGFzIHRoZSBnbG9iYWwg
+QG9wdGlvbnstLWtleXNlcnZlci1vcHRpb25zfQpmcm9tIGJlbG93LCBidXQgYXBw
+bHkgb25seSB0byB0aGlzIHBhcnRpY3VsYXIga2V5c2VydmVyLgoKTW9zdCBrZXlz
+ZXJ2ZXJzIHN5bmNocm9uaXplIHdpdGggZWFjaCBvdGhlciwgc28gdGhlcmUgaXMg
+Z2VuZXJhbGx5IG5vCm5lZWQgdG8gc2VuZCBrZXlzIHRvIG1vcmUgdGhhbiBvbmUg
+c2VydmVyLiBUaGUga2V5c2VydmVyCkBjb2Rle2hrcDovL2tleXMuZ251cGcubmV0
+fSB1c2VzIHJvdW5kIHJvYmluIEROUyB0byBnaXZlIGEgZGlmZmVyZW50CmtleXNl
+cnZlciBlYWNoIHRpbWUgeW91IHVzZSBpdC4KCkBpdGVtIC0ta2V5c2VydmVyLW9w
+dGlvbnMgQGNvZGV7bmFtZT12YWx1ZX0KQG9waW5kZXgga2V5c2VydmVyLW9wdGlv
+bnMKVGhpcyBpcyBhIHNwYWNlIG9yIGNvbW1hIGRlbGltaXRlZCBzdHJpbmcgdGhh
+dCBnaXZlcyBvcHRpb25zIGZvciB0aGUKa2V5c2VydmVyLiBPcHRpb25zIGNhbiBi
+ZSBwcmVmaXhlZCB3aXRoIGEgYG5vLScgdG8gZ2l2ZSB0aGUgb3Bwb3NpdGUKbWVh
+bmluZy4gVmFsaWQgaW1wb3J0LW9wdGlvbnMgb3IgZXhwb3J0LW9wdGlvbnMgbWF5
+IGJlIHVzZWQgaGVyZSBhcwp3ZWxsIHRvIGFwcGx5IHRvIGltcG9ydGluZyAoQG9w
+dGlvbnstLXJlY3Yta2V5fSkgb3IgZXhwb3J0aW5nCihAb3B0aW9uey0tc2VuZC1r
+ZXl9KSBhIGtleSBmcm9tIGEga2V5c2VydmVyLiBXaGlsZSBub3QgYWxsIG9wdGlv
+bnMKYXJlIGF2YWlsYWJsZSBmb3IgYWxsIGtleXNlcnZlciB0eXBlcywgc29tZSBj
+b21tb24gb3B0aW9ucyBhcmU6CgpAdGFibGUgQGFzaXMKCiAgQGl0ZW0gaW5jbHVk
+ZS1yZXZva2VkCiAgV2hlbiBzZWFyY2hpbmcgZm9yIGEga2V5IHdpdGggQG9wdGlv
+bnstLXNlYXJjaC1rZXlzfSwgaW5jbHVkZSBrZXlzIHRoYXQKICBhcmUgbWFya2Vk
+IG9uIHRoZSBrZXlzZXJ2ZXIgYXMgcmV2b2tlZC4gTm90ZSB0aGF0IG5vdCBhbGwg
+a2V5c2VydmVycwogIGRpZmZlcmVudGlhdGUgYmV0d2VlbiByZXZva2VkIGFuZCB1
+bnJldm9rZWQga2V5cywgYW5kIGZvciBzdWNoCiAga2V5c2VydmVycyB0aGlzIG9w
+dGlvbiBpcyBtZWFuaW5nbGVzcy4gTm90ZSBhbHNvIHRoYXQgbW9zdCBrZXlzZXJ2
+ZXJzIGRvCiAgbm90IGhhdmUgY3J5cHRvZ3JhcGhpYyB2ZXJpZmljYXRpb24gb2Yg
+a2V5IHJldm9jYXRpb25zLCBhbmQgc28gdHVybmluZwogIHRoaXMgb3B0aW9uIG9m
+ZiBtYXkgcmVzdWx0IGluIHNraXBwaW5nIGtleXMgdGhhdCBhcmUgaW5jb3JyZWN0
+bHkgbWFya2VkCiAgYXMgcmV2b2tlZC4KCiAgQGl0ZW0gaW5jbHVkZS1kaXNhYmxl
+ZAogIFdoZW4gc2VhcmNoaW5nIGZvciBhIGtleSB3aXRoIEBvcHRpb257LS1zZWFy
+Y2gta2V5c30sIGluY2x1ZGUga2V5cyB0aGF0CiAgYXJlIG1hcmtlZCBvbiB0aGUg
+a2V5c2VydmVyIGFzIGRpc2FibGVkLiBOb3RlIHRoYXQgdGhpcyBvcHRpb24gaXMg
+bm90CiAgdXNlZCB3aXRoIEhLUCBrZXlzZXJ2ZXJzLgoKICBAaXRlbSBhdXRvLWtl
+eS1yZXRyaWV2ZQogIFRoaXMgb3B0aW9uIGVuYWJsZXMgdGhlIGF1dG9tYXRpYyBy
+ZXRyaWV2aW5nIG9mIGtleXMgZnJvbSBhIGtleXNlcnZlcgogIHdoZW4gdmVyaWZ5
+aW5nIHNpZ25hdHVyZXMgbWFkZSBieSBrZXlzIHRoYXQgYXJlIG5vdCBvbiB0aGUg
+bG9jYWwKICBrZXlyaW5nLgoKICBOb3RlIHRoYXQgdGhpcyBvcHRpb24gbWFrZXMg
+YSAid2ViIGJ1ZyIgbGlrZSBiZWhhdmlvciBwb3NzaWJsZS4KICBLZXlzZXJ2ZXIg
+b3BlcmF0b3JzIGNhbiBzZWUgd2hpY2gga2V5cyB5b3UgcmVxdWVzdCwgc28gYnkg
+c2VuZGluZyB5b3UKICBhIG1lc3NhZ2Ugc2lnbmVkIGJ5IGEgYnJhbmQgbmV3IGtl
+eSAod2hpY2ggeW91IG5hdHVyYWxseSB3aWxsIG5vdCBoYXZlCiAgb24geW91ciBs
+b2NhbCBrZXlyaW5nKSwgdGhlIG9wZXJhdG9yIGNhbiB0ZWxsIGJvdGggeW91ciBJ
+UCBhZGRyZXNzIGFuZAogIHRoZSB0aW1lIHdoZW4geW91IHZlcmlmaWVkIHRoZSBz
+aWduYXR1cmUuCgogIEBpdGVtIGhvbm9yLWtleXNlcnZlci11cmwKICBXaGVuIHVz
+aW5nIEBvcHRpb257LS1yZWZyZXNoLWtleXN9LCBpZiB0aGUga2V5IGluIHF1ZXN0
+aW9uIGhhcyBhIHByZWZlcnJlZAogIGtleXNlcnZlciBVUkwsIHRoZW4gdXNlIHRo
+YXQgcHJlZmVycmVkIGtleXNlcnZlciB0byByZWZyZXNoIHRoZSBrZXkKICBmcm9t
+LiBJbiBhZGRpdGlvbiwgaWYgYXV0by1rZXktcmV0cmlldmUgaXMgc2V0LCBhbmQg
+dGhlIHNpZ25hdHVyZQogIGJlaW5nIHZlcmlmaWVkIGhhcyBhIHByZWZlcnJlZCBr
+ZXlzZXJ2ZXIgVVJMLCB0aGVuIHVzZSB0aGF0IHByZWZlcnJlZAogIGtleXNlcnZl
+ciB0byBmZXRjaCB0aGUga2V5IGZyb20uIE5vdGUgdGhhdCB0aGlzIG9wdGlvbiBp
+bnRyb2R1Y2VzIGEKICAid2ViIGJ1ZyI6IFRoZSBjcmVhdG9yIG9mIHRoZSBrZXkg
+Y2FuIHNlZSB3aGVuIHRoZSBrZXlzIGlzCiAgcmVmcmVzaGVkLiAgVGh1cyB0aGlz
+IG9wdGlvbiBpcyBub3QgZW5hYmxlZCBieSBkZWZhdWx0LgoKICBAaXRlbSBob25v
+ci1wa2EtcmVjb3JkCiAgSWYgYXV0by1rZXktcmV0cmlldmUgaXMgc2V0LCBhbmQg
+dGhlIHNpZ25hdHVyZSBiZWluZyB2ZXJpZmllZCBoYXMgYQogIFBLQSByZWNvcmQs
+IHRoZW4gdXNlIHRoZSBQS0EgaW5mb3JtYXRpb24gdG8gZmV0Y2ggdGhlIGtleS4g
+RGVmYXVsdHMKICB0byAieWVzIi4KCiAgQGl0ZW0gaW5jbHVkZS1zdWJrZXlzCiAg
+V2hlbiByZWNlaXZpbmcgYSBrZXksIGluY2x1ZGUgc3Via2V5cyBhcyBwb3RlbnRp
+YWwgdGFyZ2V0cy4gTm90ZSB0aGF0CiAgdGhpcyBvcHRpb24gaXMgbm90IHVzZWQg
+d2l0aCBIS1Aga2V5c2VydmVycywgYXMgdGhleSBkbyBub3Qgc3VwcG9ydAogIHJl
+dHJpZXZpbmcga2V5cyBieSBzdWJrZXkgaWQuCgogIEBpdGVtIHRpbWVvdXQKICBU
+ZWxsIHRoZSBrZXlzZXJ2ZXIgaGVscGVyIHByb2dyYW0gaG93IGxvbmcgKGluIHNl
+Y29uZHMpIHRvIHRyeSBhbmQKICBwZXJmb3JtIGEga2V5c2VydmVyIGFjdGlvbiBi
+ZWZvcmUgZ2l2aW5nIHVwLiBOb3RlIHRoYXQgcGVyZm9ybWluZwogIG11bHRpcGxl
+IGFjdGlvbnMgYXQgdGhlIHNhbWUgdGltZSB1c2VzIHRoaXMgdGltZW91dCB2YWx1
+ZSBwZXIgYWN0aW9uLgogIEZvciBleGFtcGxlLCB3aGVuIHJldHJpZXZpbmcgbXVs
+dGlwbGUga2V5cyB2aWEgQG9wdGlvbnstLXJlY3Yta2V5c30sIHRoZQogIHRpbWVv
+dXQgYXBwbGllcyBzZXBhcmF0ZWx5IHRvIGVhY2gga2V5IHJldHJpZXZhbCwgYW5k
+IG5vdCB0byB0aGUKICBAb3B0aW9uey0tcmVjdi1rZXlzfSBjb21tYW5kIGFzIGEg
+d2hvbGUuIERlZmF1bHRzIHRvIDMwIHNlY29uZHMuCgogIEBpdGVtIGh0dHAtcHJv
+eHk9QGNvZGV7dmFsdWV9CiAgVGhpcyBvcHRpb25zIGlzIGRlcHJlY2F0ZWQuCiAg
+U2V0IHRoZSBwcm94eSB0byB1c2UgZm9yIEhUVFAgYW5kIEhLUCBrZXlzZXJ2ZXJz
+LgogIFRoaXMgb3ZlcnJpZGVzIGFueSBwcm94eSBkZWZpbmVkIGluIEBmaWxle2Rp
+cm1uZ3IuY29uZn0uCgogIEBpdGVtIHZlcmJvc2UKICBUaGlzIG9wdGlvbiBoYXMg
+bm8gbW9yZSBmdW5jdGlvbiBzaW5jZSBHbnVQRyAyLjEuICBVc2UgdGhlCiAgQGNv
+ZGV7ZGlybW5ncn0gY29uZmlndXJhdGlvbiBvcHRpb25zIGluc3RlYWQuCgogIEBp
+dGVtIGRlYnVnCiAgVGhpcyBvcHRpb24gaGFzIG5vIG1vcmUgZnVuY3Rpb24gc2lu
+Y2UgR251UEcgMi4xLiAgVXNlIHRoZQogIEBjb2Rle2Rpcm1uZ3J9IGNvbmZpZ3Vy
+YXRpb24gb3B0aW9ucyBpbnN0ZWFkLgoKICBAaXRlbSBjaGVjay1jZXJ0CiAgVGhp
+cyBvcHRpb24gaGFzIG5vIG1vcmUgZnVuY3Rpb24gc2luY2UgR251UEcgMi4xLiAg
+VXNlIHRoZQogIEBjb2Rle2Rpcm1uZ3J9IGNvbmZpZ3VyYXRpb24gb3B0aW9ucyBp
+bnN0ZWFkLgoKICBAaXRlbSBjYS1jZXJ0LWZpbGUKICBUaGlzIG9wdGlvbiBoYXMg
+bm8gbW9yZSBmdW5jdGlvbiBzaW5jZSBHbnVQRyAyLjEuICBVc2UgdGhlCiAgQGNv
+ZGV7ZGlybW5ncn0gY29uZmlndXJhdGlvbiBvcHRpb25zIGluc3RlYWQuCgpAZW5k
+IHRhYmxlCgpAaXRlbSAtLWNvbXBsZXRlcy1uZWVkZWQgQGNvZGV7bn0KQG9waW5k
+ZXggY29tcGxpYW50LW5lZWRlZApOdW1iZXIgb2YgY29tcGxldGVseSB0cnVzdGVk
+IHVzZXJzIHRvIGludHJvZHVjZSBhIG5ldwprZXkgc2lnbmVyIChkZWZhdWx0cyB0
+byAxKS4KCkBpdGVtIC0tbWFyZ2luYWxzLW5lZWRlZCBAY29kZXtufQpAb3BpbmRl
+eCBtYXJnaW5hbHMtbmVlZGVkCk51bWJlciBvZiBtYXJnaW5hbGx5IHRydXN0ZWQg
+dXNlcnMgdG8gaW50cm9kdWNlIGEgbmV3CmtleSBzaWduZXIgKGRlZmF1bHRzIHRv
+IDMpCgpAaXRlbSAtLXRvZnUtZGVmYXVsdC1wb2xpY3kgQGNvZGV7YXV0b3xnb29k
+fHVua25vd258YmFkfGFza30KQG9waW5kZXggdG9mdS1kZWZhdWx0LXBvbGljeQpU
+aGUgZGVmYXVsdCBUT0ZVIHBvbGljeSAoZGVmYXVsdHMgdG8gQGNvZGV7YXV0b30p
+LiAgRm9yIG1vcmUKaW5mb3JtYXRpb24gYWJvdXQgdGhlIG1lYW5pbmcgb2YgdGhp
+cyBvcHRpb24sIEB4cmVme3RydXN0LW1vZGVsLXRvZnV9LgoKQGl0ZW0gLS10b2Z1
+LWRiLWZvcm1hdCBAY29kZXthdXRvfHNwbGl0fGZsYXR9CkBvcGluZGV4IHRvZnUt
+ZGVmYXVsdC1wb2xpY3kKVGhlIGZvcm1hdCBmb3IgdGhlIFRPRlUgREIuCgpUaGUg
+c3BsaXQgZmlsZSBmb3JtYXQgc3BsaXRzIHRoZSBkYXRhIGFjcm9zcyBtYW55IERC
+cyB1bmRlciB0aGUKQGNvZGV7dG9mdS5kfSBkaXJlY3RvcnkgKG9uZSBwZXIgZW1h
+aWwgYWRkcmVzcyBhbmQgb25lIHBlciBrZXkpLiAgVGhpcwptYWtlcyBpdCBlYXNp
+ZXIgdG8gYXV0b21hdGljYWxseSBzeW5jaHJvbml6ZSB0aGUgZGF0YSB1c2luZyBh
+IHRvb2wKc3VjaCBhcyBVbmlzb24gKEB1cmx7aHR0cHM6Ly93d3cuY2lzLnVwZW5u
+LmVkdS9+YmNwaWVyY2UvdW5pc29uL30pLApzaW5jZSB0aGUgaW5kaXZpZHVhbCBm
+aWxlcyBjaGFuZ2UgcmFyZWx5LgoKVGhlIGZsYXQgZmlsZSBmb3JtYXQga2VlcHMg
+YWxsIG9mIHRoZSBkYXRhIGluIHRoZSBzaW5nbGUgZmlsZQpAY29kZXt0b2Z1LmRi
+fS4gIFRoaXMgZm9ybWF0IHJlc3VsdHMgaW4gYmV0dGVyIHBlcmZvcm1hbmNlLgoK
+SWYgc2V0IHRvIGF1dG8gKHdoaWNoIGlzIHRoZSBkZWZhdWx0KSwgR251UEcgd2ls
+bCBmaXJzdCBjaGVjayBmb3IgdGhlCmV4aXN0ZW5jZSBvZiBAY29kZXt0b2Z1LmR9
+IGFuZCBAY29kZXt0b2Z1LmRifS4gIElmIG9uZSBvZiB0aGVzZQpleGlzdHMsIHRo
+ZSBjb3JyZXNwb25kaW5nIGZvcm1hdCBpcyB1c2VkLiAgSWYgbmVpdGhlciBvciBi
+b3RoIG9mIHRoZXNlCmV4aXN0LCB0aGVuIEdudVBHIGRlZmF1bHRzIHRvIHRoZSBA
+Y29kZXtzcGxpdH0gZm9ybWF0LiAgSW4gdGhlIGxhdHRlcgpjYXNlLCBhIHdhcm5p
+bmcgaXMgZW1pdHRlZC4KCkBpdGVtIC0tbWF4LWNlcnQtZGVwdGggQGNvZGV7bn0K
+QG9waW5kZXggbWF4LWNlcnQtZGVwdGgKTWF4aW11bSBkZXB0aCBvZiBhIGNlcnRp
+ZmljYXRpb24gY2hhaW4gKGRlZmF1bHQgaXMgNSkuCgpAaXRlbSAtLW5vLXNpZy1j
+YWNoZQpAb3BpbmRleCBuby1zaWctY2FjaGUKRG8gbm90IGNhY2hlIHRoZSB2ZXJp
+ZmljYXRpb24gc3RhdHVzIG9mIGtleSBzaWduYXR1cmVzLgpDYWNoaW5nIGdpdmVz
+IGEgbXVjaCBiZXR0ZXIgcGVyZm9ybWFuY2UgaW4ga2V5IGxpc3RpbmdzLiBIb3dl
+dmVyLCBpZgp5b3Ugc3VzcGVjdCB0aGF0IHlvdXIgcHVibGljIGtleXJpbmcgaXMg
+bm90IHNhdmUgYWdhaW5zdCB3cml0ZQptb2RpZmljYXRpb25zLCB5b3UgY2FuIHVz
+ZSB0aGlzIG9wdGlvbiB0byBkaXNhYmxlIHRoZSBjYWNoaW5nLiBJdApwcm9iYWJs
+eSBkb2VzIG5vdCBtYWtlIHNlbnNlIHRvIGRpc2FibGUgaXQgYmVjYXVzZSBhbGwg
+a2luZCBvZiBkYW1hZ2UKY2FuIGJlIGRvbmUgaWYgc29tZW9uZSBlbHNlIGhhcyB3
+cml0ZSBhY2Nlc3MgdG8geW91ciBwdWJsaWMga2V5cmluZy4KCkBpdGVtIC0tYXV0
+by1jaGVjay10cnVzdGRiCkBpdGVteCAtLW5vLWF1dG8tY2hlY2stdHJ1c3RkYgpA
+b3BpbmRleCBhdXRvLWNoZWNrLXRydXN0ZGIKSWYgR251UEcgZmVlbHMgdGhhdCBp
+dHMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIFdlYiBvZiBUcnVzdCBoYXMgdG8gYmUK
+dXBkYXRlZCwgaXQgYXV0b21hdGljYWxseSBydW5zIHRoZSBAb3B0aW9uey0tY2hl
+Y2stdHJ1c3RkYn0gY29tbWFuZAppbnRlcm5hbGx5LiAgVGhpcyBtYXkgYmUgYSB0
+aW1lIGNvbnN1bWluZwpwcm9jZXNzLiBAb3B0aW9uey0tbm8tYXV0by1jaGVjay10
+cnVzdGRifSBkaXNhYmxlcyB0aGlzIG9wdGlvbi4KCkBpdGVtIC0tdXNlLWFnZW50
+CkBpdGVteCAtLW5vLXVzZS1hZ2VudApAb3BpbmRleCB1c2UtYWdlbnQKVGhpcyBp
+cyBkdW1teSBvcHRpb24uIEBjb21tYW5ke0BncGduYW1lfSBhbHdheXMgcmVxdWly
+ZXMgdGhlIGFnZW50LgoKQGl0ZW0gLS1ncGctYWdlbnQtaW5mbwpAb3BpbmRleCBn
+cGctYWdlbnQtaW5mbwpUaGlzIGlzIGR1bW15IG9wdGlvbi4gSXQgaGFzIG5vIGVm
+ZmVjdCB3aGVuIHVzZWQgd2l0aCBAY29tbWFuZHtncGcyfS4KCgpAaXRlbSAtLWFn
+ZW50LXByb2dyYW0gQHZhcntmaWxlfQpAb3BpbmRleCBhZ2VudC1wcm9ncmFtClNw
+ZWNpZnkgYW4gYWdlbnQgcHJvZ3JhbSB0byBiZSB1c2VkIGZvciBzZWNyZXQga2V5
+IG9wZXJhdGlvbnMuICBUaGUKZGVmYXVsdCB2YWx1ZSBpcyBkZXRlcm1pbmVkIGJ5
+IHJ1bm5pbmcgQGNvbW1hbmR7Z3BnY29uZn0gd2l0aCB0aGUKb3B0aW9uIEBvcHRp
+b257LS1saXN0LWRpcnN9LiAgTm90ZSB0aGF0IHRoZSBwaXBlIHN5bWJvbCAoQGNv
+ZGV7fH0pIGlzCnVzZWQgZm9yIGEgcmVncmVzc2lvbiB0ZXN0IHN1aXRlIGhhY2sg
+YW5kIG1heSB0aHVzIG5vdCBiZSB1c2VkIGluIHRoZQpmaWxlIG5hbWUuCgpAaXRl
+bSAtLWRpcm1uZ3ItcHJvZ3JhbSBAdmFye2ZpbGV9CkBvcGluZGV4IGRpcm1uZ3It
+cHJvZ3JhbQpTcGVjaWZ5IGEgZGlybW5nciBwcm9ncmFtIHRvIGJlIHVzZWQgZm9y
+IGtleXNlcnZlciBhY2Nlc3MuICBUaGUKZGVmYXVsdCB2YWx1ZSBpcyBAZmlsZXtA
+dmFsdWV7QklORElSfS9kaXJtbmdyfS4gIFRoaXMgaXMgb25seSB1c2VkIGFzIGEK
+ZmFsbGJhY2sgd2hlbiB0aGUgZW52aXJvbm1lbnQgdmFyaWFibGUgQGNvZGV7RElS
+TU5HUl9JTkZPfSBpcyBub3Qgc2V0IG9yCmEgcnVubmluZyBkaXJtbmdyIGNhbm5v
+dCBiZSBjb25uZWN0ZWQuCgpAaXRlbSAtLW5vLWF1dG9zdGFydApAb3BpbmRleCBu
+by1hdXRvc3RhcnQKRG8gbm90IHN0YXJ0IHRoZSBncGctYWdlbnQgb3IgdGhlIGRp
+cm1uZ3IgaWYgaXQgaGFzIG5vdCB5ZXQgYmVlbgpzdGFydGVkIGFuZCBpdHMgc2Vy
+dmljZSBpcyByZXF1aXJlZC4gIFRoaXMgb3B0aW9uIGlzIG1vc3RseSB1c2VmdWwg
+b24KbWFjaGluZXMgd2hlcmUgdGhlIGNvbm5lY3Rpb24gdG8gZ3BnLWFnZW50IGhh
+cyBiZWVuIHJlZGlyZWN0ZWQgdG8KYW5vdGhlciBtYWNoaW5lcy4gIElmIGRpcm1u
+Z3IgaXMgcmVxdWlyZWQgb24gdGhlIHJlbW90ZSBtYWNoaW5lLCBpdAptYXkgYmUg
+c3RhcnRlZCBtYW51YWxseSB1c2luZyBAY29tbWFuZHtncGdjb25mIC0tbGF1bmNo
+IGRpcm1uZ3J9LgoKQGl0ZW0gLS1sb2NrLW9uY2UKQG9waW5kZXggbG9jay1vbmNl
+CkxvY2sgdGhlIGRhdGFiYXNlcyB0aGUgZmlyc3QgdGltZSBhIGxvY2sgaXMgcmVx
+dWVzdGVkCmFuZCBkbyBub3QgcmVsZWFzZSB0aGUgbG9jayB1bnRpbCB0aGUgcHJv
+Y2Vzcwp0ZXJtaW5hdGVzLgoKQGl0ZW0gLS1sb2NrLW11bHRpcGxlCkBvcGluZGV4
+IGxvY2stbXVsdGlwbGUKUmVsZWFzZSB0aGUgbG9ja3MgZXZlcnkgdGltZSBhIGxv
+Y2sgaXMgbm8gbG9uZ2VyCm5lZWRlZC4gVXNlIHRoaXMgdG8gb3ZlcnJpZGUgYSBw
+cmV2aW91cyBAb3B0aW9uey0tbG9jay1vbmNlfQpmcm9tIGEgY29uZmlnIGZpbGUu
+CgpAaXRlbSAtLWxvY2stbmV2ZXIKQG9waW5kZXggbG9jay1uZXZlcgpEaXNhYmxl
+IGxvY2tpbmcgZW50aXJlbHkuIFRoaXMgb3B0aW9uIHNob3VsZCBiZSB1c2VkIG9u
+bHkgaW4gdmVyeQpzcGVjaWFsIGVudmlyb25tZW50cywgd2hlcmUgaXQgY2FuIGJl
+IGFzc3VyZWQgdGhhdCBvbmx5IG9uZSBwcm9jZXNzCmlzIGFjY2Vzc2luZyB0aG9z
+ZSBmaWxlcy4gQSBib290YWJsZSBmbG9wcHkgd2l0aCBhIHN0YW5kLWFsb25lCmVu
+Y3J5cHRpb24gc3lzdGVtIHdpbGwgcHJvYmFibHkgdXNlIHRoaXMuIEltcHJvcGVy
+IHVzYWdlIG9mIHRoaXMKb3B0aW9uIG1heSBsZWFkIHRvIGRhdGEgYW5kIGtleSBj
+b3JydXB0aW9uLgoKQGl0ZW0gLS1leGl0LW9uLXN0YXR1cy13cml0ZS1lcnJvcgpA
+b3BpbmRleCBleGl0LW9uLXN0YXR1cy13cml0ZS1lcnJvcgpUaGlzIG9wdGlvbiB3
+aWxsIGNhdXNlIHdyaXRlIGVycm9ycyBvbiB0aGUgc3RhdHVzIEZEIHRvIGltbWVk
+aWF0ZWx5CnRlcm1pbmF0ZSB0aGUgcHJvY2Vzcy4gVGhhdCBzaG91bGQgaW4gZmFj
+dCBiZSB0aGUgZGVmYXVsdCBidXQgaXQgbmV2ZXIKd29ya2VkIHRoaXMgd2F5IGFu
+ZCB0aHVzIHdlIG5lZWQgYW4gb3B0aW9uIHRvIGVuYWJsZSB0aGlzLCBzbyB0aGF0
+IHRoZQpjaGFuZ2Ugd29uJ3QgYnJlYWsgYXBwbGljYXRpb25zIHdoaWNoIGNsb3Nl
+IHRoZWlyIGVuZCBvZiBhIHN0YXR1cyBmZApjb25uZWN0ZWQgcGlwZSB0b28gZWFy
+bHkuIFVzaW5nIHRoaXMgb3B0aW9uIGFsb25nIHdpdGgKQG9wdGlvbnstLWVuYWJs
+ZS1wcm9ncmVzcy1maWx0ZXJ9IG1heSBiZSB1c2VkIHRvIGNsZWFubHkgY2FuY2Vs
+IGxvbmcKcnVubmluZyBncGcgb3BlcmF0aW9ucy4KCkBpdGVtIC0tbGltaXQtY2Fy
+ZC1pbnNlcnQtdHJpZXMgQGNvZGV7bn0KQG9waW5kZXggbGltaXQtY2FyZC1pbnNl
+cnQtdHJpZXMKV2l0aCBAY29kZXtufSBncmVhdGVyIHRoYW4gMCB0aGUgbnVtYmVy
+IG9mIHByb21wdHMgYXNraW5nIHRvIGluc2VydCBhCnNtYXJ0Y2FyZCBnZXRzIGxp
+bWl0ZWQgdG8gTi0xLiBUaHVzIHdpdGggYSB2YWx1ZSBvZiAxIGdwZyB3b24ndCBh
+dAphbGwgYXNrIHRvIGluc2VydCBhIGNhcmQgaWYgbm9uZSBoYXMgYmVlbiBpbnNl
+cnRlZCBhdCBzdGFydHVwLiBUaGlzCm9wdGlvbiBpcyB1c2VmdWwgaW4gdGhlIGNv
+bmZpZ3VyYXRpb24gZmlsZSBpbiBjYXNlIGFuIGFwcGxpY2F0aW9uIGRvZXMKbm90
+IGtub3cgYWJvdXQgdGhlIHNtYXJ0Y2FyZCBzdXBwb3J0IGFuZCB3YWl0cyBhZCBp
+bmZpbml0dW0gZm9yIGFuCmluc2VydGVkIGNhcmQuCgpAaXRlbSAtLW5vLXJhbmRv
+bS1zZWVkLWZpbGUKQG9waW5kZXggbm8tcmFuZG9tLXNlZWQtZmlsZQpHbnVQRyB1
+c2VzIGEgZmlsZSB0byBzdG9yZSBpdHMgaW50ZXJuYWwgcmFuZG9tIHBvb2wgb3Zl
+ciBpbnZvY2F0aW9ucy4KVGhpcyBtYWtlcyByYW5kb20gZ2VuZXJhdGlvbiBmYXN0
+ZXI7IGhvd2V2ZXIgc29tZXRpbWVzIHdyaXRlIG9wZXJhdGlvbnMKYXJlIG5vdCBk
+ZXNpcmVkLiBUaGlzIG9wdGlvbiBjYW4gYmUgdXNlZCB0byBhY2hpZXZlIHRoYXQg
+d2l0aCB0aGUgY29zdCBvZgpzbG93ZXIgcmFuZG9tIGdlbmVyYXRpb24uCgpAaXRl
+bSAtLW5vLWdyZWV0aW5nCkBvcGluZGV4IG5vLWdyZWV0aW5nClN1cHByZXNzIHRo
+ZSBpbml0aWFsIGNvcHlyaWdodCBtZXNzYWdlLgoKQGl0ZW0gLS1uby1zZWNtZW0t
+d2FybmluZwpAb3BpbmRleCBuby1zZWNtZW0td2FybmluZwpTdXBwcmVzcyB0aGUg
+d2FybmluZyBhYm91dCAidXNpbmcgaW5zZWN1cmUgbWVtb3J5Ii4KCkBpdGVtIC0t
+bm8tcGVybWlzc2lvbi13YXJuaW5nCkBvcGluZGV4IHBlcm1pc3Npb24td2Fybmlu
+ZwpTdXBwcmVzcyB0aGUgd2FybmluZyBhYm91dCB1bnNhZmUgZmlsZSBhbmQgaG9t
+ZSBkaXJlY3RvcnkgKEBvcHRpb257LS1ob21lZGlyfSkKcGVybWlzc2lvbnMuIE5v
+dGUgdGhhdCB0aGUgcGVybWlzc2lvbiBjaGVja3MgdGhhdCBHbnVQRyBwZXJmb3Jt
+cyBhcmUKbm90IGludGVuZGVkIHRvIGJlIGF1dGhvcml0YXRpdmUsIGJ1dCByYXRo
+ZXIgdGhleSBzaW1wbHkgd2FybiBhYm91dApjZXJ0YWluIGNvbW1vbiBwZXJtaXNz
+aW9uIHByb2JsZW1zLiBEbyBub3QgYXNzdW1lIHRoYXQgdGhlIGxhY2sgb2YgYQp3
+YXJuaW5nIG1lYW5zIHRoYXQgeW91ciBzeXN0ZW0gaXMgc2VjdXJlLgoKTm90ZSB0
+aGF0IHRoZSB3YXJuaW5nIGZvciB1bnNhZmUgQG9wdGlvbnstLWhvbWVkaXJ9IHBl
+cm1pc3Npb25zIGNhbm5vdCBiZQpzdXBwcmVzc2VkIGluIHRoZSBncGcuY29uZiBm
+aWxlLCBhcyB0aGlzIHdvdWxkIGFsbG93IGFuIGF0dGFja2VyIHRvCnBsYWNlIGFu
+IHVuc2FmZSBncGcuY29uZiBmaWxlIGluIHBsYWNlLCBhbmQgdXNlIHRoaXMgZmls
+ZSB0byBzdXBwcmVzcwp3YXJuaW5ncyBhYm91dCBpdHNlbGYuIFRoZSBAb3B0aW9u
+ey0taG9tZWRpcn0gcGVybWlzc2lvbnMgd2FybmluZyBtYXkgb25seSBiZQpzdXBw
+cmVzc2VkIG9uIHRoZSBjb21tYW5kIGxpbmUuCgpAaXRlbSAtLW5vLW1kYy13YXJu
+aW5nCkBvcGluZGV4IG5vLW1kYy13YXJuaW5nClN1cHByZXNzIHRoZSB3YXJuaW5n
+IGFib3V0IG1pc3NpbmcgTURDIGludGVncml0eSBwcm90ZWN0aW9uLgoKQGl0ZW0g
+LS1yZXF1aXJlLXNlY21lbQpAaXRlbXggLS1uby1yZXF1aXJlLXNlY21lbQpAb3Bp
+bmRleCByZXF1aXJlLXNlY21lbQpSZWZ1c2UgdG8gcnVuIGlmIEdudVBHIGNhbm5v
+dCBnZXQgc2VjdXJlIG1lbW9yeS4gRGVmYXVsdHMgdG8gbm8KKGkuZS4gcnVuLCBi
+dXQgZ2l2ZSBhIHdhcm5pbmcpLgoKCkBpdGVtIC0tcmVxdWlyZS1jcm9zcy1jZXJ0
+aWZpY2F0aW9uCkBpdGVteCAtLW5vLXJlcXVpcmUtY3Jvc3MtY2VydGlmaWNhdGlv
+bgpAb3BpbmRleCByZXF1aXJlLWNyb3NzLWNlcnRpZmljYXRpb24KV2hlbiB2ZXJp
+ZnlpbmcgYSBzaWduYXR1cmUgbWFkZSBmcm9tIGEgc3Via2V5LCBlbnN1cmUgdGhh
+dCB0aGUgY3Jvc3MKY2VydGlmaWNhdGlvbiAiYmFjayBzaWduYXR1cmUiIG9uIHRo
+ZSBzdWJrZXkgaXMgcHJlc2VudCBhbmQgdmFsaWQuICBUaGlzCnByb3RlY3RzIGFn
+YWluc3QgYSBzdWJ0bGUgYXR0YWNrIGFnYWluc3Qgc3Via2V5cyB0aGF0IGNhbiBz
+aWduLgpEZWZhdWx0cyB0byBAb3B0aW9uey0tcmVxdWlyZS1jcm9zcy1jZXJ0aWZp
+Y2F0aW9ufSBmb3IKQGNvbW1hbmR7QGdwZ25hbWV9LgoKQGl0ZW0gLS1leHBlcnQK
+QGl0ZW14IC0tbm8tZXhwZXJ0CkBvcGluZGV4IGV4cGVydApBbGxvdyB0aGUgdXNl
+ciB0byBkbyBjZXJ0YWluIG5vbnNlbnNpY2FsIG9yICJzaWxseSIgdGhpbmdzIGxp
+a2UKc2lnbmluZyBhbiBleHBpcmVkIG9yIHJldm9rZWQga2V5LCBvciBjZXJ0YWlu
+IHBvdGVudGlhbGx5IGluY29tcGF0aWJsZQp0aGluZ3MgbGlrZSBnZW5lcmF0aW5n
+IHVudXN1YWwga2V5IHR5cGVzLiBUaGlzIGFsc28gZGlzYWJsZXMgY2VydGFpbgp3
+YXJuaW5nIG1lc3NhZ2VzIGFib3V0IHBvdGVudGlhbGx5IGluY29tcGF0aWJsZSBh
+Y3Rpb25zLiBBcyB0aGUgbmFtZQppbXBsaWVzLCB0aGlzIG9wdGlvbiBpcyBmb3Ig
+ZXhwZXJ0cyBvbmx5LiBJZiB5b3UgZG9uJ3QgZnVsbHkKdW5kZXJzdGFuZCB0aGUg
+aW1wbGljYXRpb25zIG9mIHdoYXQgaXQgYWxsb3dzIHlvdSB0byBkbywgbGVhdmUg
+dGhpcwpvZmYuIEBvcHRpb257LS1uby1leHBlcnR9IGRpc2FibGVzIHRoaXMgb3B0
+aW9uLgoKQGVuZCB0YWJsZQoKCkBjICoqKioqKioqKioqKioqKioqKioqKioqKioq
+KioqKioqKioqKioqKioqKioKQGMgKioqKioqKiogIEtFWSBSRUxBVEVEIE9QVElP
+TlMgICoqKioqKioqKioqKgpAYyAqKioqKioqKioqKioqKioqKioqKioqKioqKioq
+KioqKioqKioqKioqKioqCkBub2RlIEdQRyBLZXkgcmVsYXRlZCBPcHRpb25zCkBz
+dWJzZWN0aW9uIEtleSByZWxhdGVkIG9wdGlvbnMKCkB0YWJsZSBAZ251cGd0YWJv
+cHQKCkBpdGVtIC0tcmVjaXBpZW50IEB2YXJ7bmFtZX0KQGl0ZW14IC1yCkBvcGlu
+ZGV4IHJlY2lwaWVudApFbmNyeXB0IGZvciB1c2VyIGlkIEB2YXJ7bmFtZX0uIElm
+IHRoaXMgb3B0aW9uIG9yCkBvcHRpb257LS1oaWRkZW4tcmVjaXBpZW50fSBpcyBu
+b3Qgc3BlY2lmaWVkLCBHbnVQRyBhc2tzIGZvciB0aGUgdXNlci1pZAp1bmxlc3Mg
+QG9wdGlvbnstLWRlZmF1bHQtcmVjaXBpZW50fSBpcyBnaXZlbi4KCkBpdGVtIC0t
+aGlkZGVuLXJlY2lwaWVudCBAdmFye25hbWV9CkBpdGVteCAtUgpAb3BpbmRleCBo
+aWRkZW4tcmVjaXBpZW50CkVuY3J5cHQgZm9yIHVzZXIgSUQgQHZhcntuYW1lfSwg
+YnV0IGhpZGUgdGhlIGtleSBJRCBvZiB0aGlzIHVzZXIncwprZXkuIFRoaXMgb3B0
+aW9uIGhlbHBzIHRvIGhpZGUgdGhlIHJlY2VpdmVyIG9mIHRoZSBtZXNzYWdlIGFu
+ZCBpcyBhCmxpbWl0ZWQgY291bnRlcm1lYXN1cmUgYWdhaW5zdCB0cmFmZmljIGFu
+YWx5c2lzLiBJZiB0aGlzIG9wdGlvbiBvcgpAb3B0aW9uey0tcmVjaXBpZW50fSBp
+cyBub3Qgc3BlY2lmaWVkLCBHbnVQRyBhc2tzIGZvciB0aGUgdXNlciBJRCB1bmxl
+c3MKQG9wdGlvbnstLWRlZmF1bHQtcmVjaXBpZW50fSBpcyBnaXZlbi4KCkBpdGVt
+IC0tZW5jcnlwdC10byBAY29kZXtuYW1lfQpAb3BpbmRleCBlbmNyeXB0LXRvClNh
+bWUgYXMgQG9wdGlvbnstLXJlY2lwaWVudH0gYnV0IHRoaXMgb25lIGlzIGludGVu
+ZGVkIGZvciB1c2UgaW4gdGhlCm9wdGlvbnMgZmlsZSBhbmQgbWF5IGJlIHVzZWQg
+d2l0aCB5b3VyIG93biB1c2VyLWlkIGFzIGFuCiJlbmNyeXB0LXRvLXNlbGYiLiBU
+aGVzZSBrZXlzIGFyZSBvbmx5IHVzZWQgd2hlbiB0aGVyZSBhcmUgb3RoZXIKcmVj
+aXBpZW50cyBnaXZlbiBlaXRoZXIgYnkgdXNlIG9mIEBvcHRpb257LS1yZWNpcGll
+bnR9IG9yIGJ5IHRoZSBhc2tlZAp1c2VyIGlkLiAgTm8gdHJ1c3QgY2hlY2tpbmcg
+aXMgcGVyZm9ybWVkIGZvciB0aGVzZSB1c2VyIGlkcyBhbmQgZXZlbgpkaXNhYmxl
+ZCBrZXlzIGNhbiBiZSB1c2VkLgoKQGl0ZW0gLS1oaWRkZW4tZW5jcnlwdC10byBA
+Y29kZXtuYW1lfQpAb3BpbmRleCBoaWRkZW4tZW5jcnlwdC10bwpTYW1lIGFzIEBv
+cHRpb257LS1oaWRkZW4tcmVjaXBpZW50fSBidXQgdGhpcyBvbmUgaXMgaW50ZW5k
+ZWQgZm9yIHVzZSBpbiB0aGUKb3B0aW9ucyBmaWxlIGFuZCBtYXkgYmUgdXNlZCB3
+aXRoIHlvdXIgb3duIHVzZXItaWQgYXMgYSBoaWRkZW4KImVuY3J5cHQtdG8tc2Vs
+ZiIuIFRoZXNlIGtleXMgYXJlIG9ubHkgdXNlZCB3aGVuIHRoZXJlIGFyZSBvdGhl
+cgpyZWNpcGllbnRzIGdpdmVuIGVpdGhlciBieSB1c2Ugb2YgQG9wdGlvbnstLXJl
+Y2lwaWVudH0gb3IgYnkgdGhlIGFza2VkIHVzZXIgaWQuCk5vIHRydXN0IGNoZWNr
+aW5nIGlzIHBlcmZvcm1lZCBmb3IgdGhlc2UgdXNlciBpZHMgYW5kIGV2ZW4gZGlz
+YWJsZWQKa2V5cyBjYW4gYmUgdXNlZC4KCkBpdGVtIC0tZW5jcnlwdC10by1kZWZh
+dWx0LWtleQpAb3BpbmRleCBlbmNyeXB0LXRvLWRlZmF1bHQta2V5CklmIHRoZSBk
+ZWZhdWx0IHNlY3JldCBrZXkgaXMgdGFrZW4gZnJvbSBAb3B0aW9uey0tZGVmYXVs
+dC1rZXl9LCB0aGVuCmFsc28gZW5jcnlwdCB0byB0aGF0IGtleS4KCkBpdGVtIC0t
+bm8tZW5jcnlwdC10bwpAb3BpbmRleCBuby1lbmNyeXB0LXRvCkRpc2FibGUgdGhl
+IHVzZSBvZiBhbGwgQG9wdGlvbnstLWVuY3J5cHQtdG99IGFuZApAb3B0aW9uey0t
+aGlkZGVuLWVuY3J5cHQtdG99IGtleXMuCgpAaXRlbSAtLWdyb3VwIEBjb2Rle25h
+bWU9dmFsdWUxIH0KQG9waW5kZXggZ3JvdXAKU2V0cyB1cCBhIG5hbWVkIGdyb3Vw
+LCB3aGljaCBpcyBzaW1pbGFyIHRvIGFsaWFzZXMgaW4gZW1haWwgcHJvZ3JhbXMu
+CkFueSB0aW1lIHRoZSBncm91cCBuYW1lIGlzIGEgcmVjaXBpZW50IChAb3B0aW9u
+ey1yfSBvcgpAb3B0aW9uey0tcmVjaXBpZW50fSksIGl0IHdpbGwgYmUgZXhwYW5k
+ZWQgdG8gdGhlIHZhbHVlcwpzcGVjaWZpZWQuIE11bHRpcGxlIGdyb3VwcyB3aXRo
+IHRoZSBzYW1lIG5hbWUgYXJlIGF1dG9tYXRpY2FsbHkgbWVyZ2VkCmludG8gYSBz
+aW5nbGUgZ3JvdXAuCgpUaGUgdmFsdWVzIGFyZSBAY29kZXtrZXkgSURzfSBvciBm
+aW5nZXJwcmludHMsIGJ1dCBhbnkga2V5IGRlc2NyaXB0aW9uCmlzIGFjY2VwdGVk
+LiBOb3RlIHRoYXQgYSB2YWx1ZSB3aXRoIHNwYWNlcyBpbiBpdCB3aWxsIGJlIHRy
+ZWF0ZWQgYXMKdHdvIGRpZmZlcmVudCB2YWx1ZXMuIE5vdGUgYWxzbyB0aGVyZSBp
+cyBvbmx5IG9uZSBsZXZlbCBvZiBleHBhbnNpb24KLS0tIHlvdSBjYW5ub3QgbWFr
+ZSBhbiBncm91cCB0aGF0IHBvaW50cyB0byBhbm90aGVyIGdyb3VwLiBXaGVuIHVz
+ZWQKZnJvbSB0aGUgY29tbWFuZCBsaW5lLCBpdCBtYXkgYmUgbmVjZXNzYXJ5IHRv
+IHF1b3RlIHRoZSBhcmd1bWVudCB0bwp0aGlzIG9wdGlvbiB0byBwcmV2ZW50IHRo
+ZSBzaGVsbCBmcm9tIHRyZWF0aW5nIGl0IGFzIG11bHRpcGxlCmFyZ3VtZW50cy4K
+CkBpdGVtIC0tdW5ncm91cCBAY29kZXtuYW1lfQpAb3BpbmRleCB1bmdyb3VwClJl
+bW92ZSBhIGdpdmVuIGVudHJ5IGZyb20gdGhlIEBvcHRpb257LS1ncm91cH0gbGlz
+dC4KCkBpdGVtIC0tbm8tZ3JvdXBzCkBvcGluZGV4IG5vLWdyb3VwcwpSZW1vdmUg
+YWxsIGVudHJpZXMgZnJvbSB0aGUgQG9wdGlvbnstLWdyb3VwfSBsaXN0LgoKQGl0
+ZW0gLS1sb2NhbC11c2VyIEB2YXJ7bmFtZX0KQGl0ZW14IC11CkBvcGluZGV4IGxv
+Y2FsLXVzZXIKVXNlIEB2YXJ7bmFtZX0gYXMgdGhlIGtleSB0byBzaWduIHdpdGgu
+IE5vdGUgdGhhdCB0aGlzIG9wdGlvbiBvdmVycmlkZXMKQG9wdGlvbnstLWRlZmF1
+bHQta2V5fS4KCkBpdGVtIC0tdHJ5LXNlY3JldC1rZXkgQHZhcntuYW1lfQpAb3Bp
+bmRleCB0cnktc2VjcmV0LWtleQpGb3IgaGlkZGVuIHJlY2lwaWVudHMgR1BHIG5l
+ZWRzIHRvIGtub3cgdGhlIGtleXMgdG8gdXNlIGZvciB0cmlhbApkZWNyeXB0aW9u
+LiAgVGhlIGtleSBzZXQgd2l0aCBAb3B0aW9uey0tZGVmYXVsdC1rZXl9IGlzIGFs
+d2F5cyB0cmllZApmaXJzdCwgYnV0IHRoaXMgaXMgb2Z0ZW4gbm90IHN1ZmZpY2ll
+bnQuICBUaGlzIG9wdGlvbiBhbGxvd3MgdG8gc2V0IG1vcmUKa2V5cyB0byBiZSB1
+c2VkIGZvciB0cmlhbCBkZWNyeXB0aW9uLiAgQWx0aG91Z2ggYW55IHZhbGlkIHVz
+ZXItaWQKc3BlY2lmaWNhdGlvbiBtYXkgYmUgdXNlZCBmb3IgQHZhcntuYW1lfSBp
+dCBtYWtlcyBzZW5zZSB0byB1c2UgYXQgbGVhc3QKdGhlIGxvbmcga2V5aWQgdG8g
+YXZvaWQgYW1iaWd1aXRpZXMuICBOb3RlIHRoYXQgZ3BnLWFnZW50IG1pZ2h0IHBv
+cCB1cCBhCnBpbmVudHJ5IGZvciBhIGxvdCBrZXlzIHRvIGRvIHRoZSB0cmlhbCBk
+ZWNyeXB0aW9uLiAgSWYgeW91IHdhbnQgdG8gc3RvcAphbGwgZnVydGhlciB0cmlh
+bCBkZWNyeXB0aW9uIHlvdSBtYXkgdXNlIGNsb3NlLXdpbmRvdyBidXR0b24gaW5z
+dGVhZCBvZgp0aGUgY2FuY2VsIGJ1dHRvbi4KCkBpdGVtIC0tdHJ5LWFsbC1zZWNy
+ZXRzCkBvcGluZGV4IHRyeS1hbGwtc2VjcmV0cwpEb24ndCBsb29rIGF0IHRoZSBr
+ZXkgSUQgYXMgc3RvcmVkIGluIHRoZSBtZXNzYWdlIGJ1dCB0cnkgYWxsIHNlY3Jl
+dAprZXlzIGluIHR1cm4gdG8gZmluZCB0aGUgcmlnaHQgZGVjcnlwdGlvbiBrZXku
+IFRoaXMgb3B0aW9uIGZvcmNlcyB0aGUKYmVoYXZpb3VyIGFzIHVzZWQgYnkgYW5v
+bnltb3VzIHJlY2lwaWVudHMgKGNyZWF0ZWQgYnkgdXNpbmcKQG9wdGlvbnstLXRo
+cm93LWtleWlkc30gb3IgQG9wdGlvbnstLWhpZGRlbi1yZWNpcGllbnR9KSBhbmQg
+bWlnaHQgY29tZQpoYW5keSBpbiBjYXNlIHdoZXJlIGFuIGVuY3J5cHRlZCBtZXNz
+YWdlIGNvbnRhaW5zIGEgYm9ndXMga2V5IElELgoKQGl0ZW0gLS1za2lwLWhpZGRl
+bi1yZWNpcGllbnRzCkBpdGVteCAtLW5vLXNraXAtaGlkZGVuLXJlY2lwaWVudHMK
+QG9waW5kZXggc2tpcC1oaWRkZW4tcmVjaXBpZW50cwpAb3BpbmRleCBuby1za2lw
+LWhpZGRlbi1yZWNpcGllbnRzCkR1cmluZyBkZWNyeXB0aW9uIHNraXAgYWxsIGFu
+b255bW91cyByZWNpcGllbnRzLiAgVGhpcyBvcHRpb24gaGVscHMgaW4KdGhlIGNh
+c2UgdGhhdCBwZW9wbGUgdXNlIHRoZSBoaWRkZW4gcmVjaXBpZW50cyBmZWF0dXJl
+IHRvIGhpZGUgdGhlcmUKb3duIGVuY3J5cHQtdG8ga2V5IGZyb20gb3RoZXJzLiAg
+SWYgb25lc2VsZiBoYXMgbWFueSBzZWNyZXQga2V5cyB0aGlzCm1heSBsZWFkIHRv
+IGEgbWFqb3IgYW5ub3lhbmNlIGJlY2F1c2UgYWxsIGtleXMgYXJlIHRyaWVkIGlu
+IHR1cm4gdG8KZGVjcnlwdCBzb21ldGhpbmcgd2hpY2ggd2FzIG5vdCByZWFsbHkg
+aW50ZW5kZWQgZm9yIGl0LiAgVGhlIGRyYXdiYWNrCm9mIHRoaXMgb3B0aW9uIGlz
+IHRoYXQgaXQgaXMgY3VycmVudGx5IG5vdCBwb3NzaWJsZSB0byBkZWNyeXB0IGEK
+bWVzc2FnZSB3aGljaCBpbmNsdWRlcyByZWFsIGFub255bW91cyByZWNpcGllbnRz
+LgoKCkBlbmQgdGFibGUKCkBjICoqKioqKioqKioqKioqKioqKioqKioqKioqKioq
+KioqKioqKioqKioqKioKQGMgKioqKioqKiogIElOUFVUIEFORCBPVVRQVVQgICoq
+KioqKioqKioqKioqKgpAYyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
+KioqKioqKioqKioqCkBub2RlIEdQRyBJbnB1dCBhbmQgT3V0cHV0CkBzdWJzZWN0
+aW9uIElucHV0IGFuZCBPdXRwdXQKCkB0YWJsZSBAZ251cGd0YWJvcHQKCkBpdGVt
+IC0tYXJtb3IKQGl0ZW14IC1hCkBvcGluZGV4IGFybW9yCkNyZWF0ZSBBU0NJSSBh
+cm1vcmVkIG91dHB1dC4gIFRoZSBkZWZhdWx0IGlzIHRvIGNyZWF0ZSB0aGUgYmlu
+YXJ5Ck9wZW5QR1AgZm9ybWF0LgoKQGl0ZW0gLS1uby1hcm1vcgpAb3BpbmRleCBu
+by1hcm1vcgpBc3N1bWUgdGhlIGlucHV0IGRhdGEgaXMgbm90IGluIEFTQ0lJIGFy
+bW9yZWQgZm9ybWF0LgoKQGl0ZW0gLS1vdXRwdXQgQHZhcntmaWxlfQpAaXRlbXgg
+LW8gQHZhcntmaWxlfQpAb3BpbmRleCBvdXRwdXQKV3JpdGUgb3V0cHV0IHRvIEB2
+YXJ7ZmlsZX0uCgpAaXRlbSAtLW1heC1vdXRwdXQgQGNvZGV7bn0KQG9waW5kZXgg
+bWF4LW91dHB1dApUaGlzIG9wdGlvbiBzZXRzIGEgbGltaXQgb24gdGhlIG51bWJl
+ciBvZiBieXRlcyB0aGF0IHdpbGwgYmUgZ2VuZXJhdGVkCndoZW4gcHJvY2Vzc2lu
+ZyBhIGZpbGUuIFNpbmNlIE9wZW5QR1Agc3VwcG9ydHMgdmFyaW91cyBsZXZlbHMg
+b2YKY29tcHJlc3Npb24sIGl0IGlzIHBvc3NpYmxlIHRoYXQgdGhlIHBsYWludGV4
+dCBvZiBhIGdpdmVuIG1lc3NhZ2UgbWF5IGJlCnNpZ25pZmljYW50bHkgbGFyZ2Vy
+IHRoYW4gdGhlIG9yaWdpbmFsIE9wZW5QR1AgbWVzc2FnZS4gV2hpbGUgR251UEcK
+d29ya3MgcHJvcGVybHkgd2l0aCBzdWNoIG1lc3NhZ2VzLCB0aGVyZSBpcyBvZnRl
+biBhIGRlc2lyZSB0byBzZXQgYQptYXhpbXVtIGZpbGUgc2l6ZSB0aGF0IHdpbGwg
+YmUgZ2VuZXJhdGVkIGJlZm9yZSBwcm9jZXNzaW5nIGlzIGZvcmNlZCB0bwpzdG9w
+IGJ5IHRoZSBPUyBsaW1pdHMuIERlZmF1bHRzIHRvIDAsIHdoaWNoIG1lYW5zICJu
+byBsaW1pdCIuCgpAaXRlbSAtLWltcG9ydC1vcHRpb25zIEBjb2Rle3BhcmFtZXRl
+cnN9CkBvcGluZGV4IGltcG9ydC1vcHRpb25zClRoaXMgaXMgYSBzcGFjZSBvciBj
+b21tYSBkZWxpbWl0ZWQgc3RyaW5nIHRoYXQgZ2l2ZXMgb3B0aW9ucyBmb3IKaW1w
+b3J0aW5nIGtleXMuIE9wdGlvbnMgY2FuIGJlIHByZXBlbmRlZCB3aXRoIGEgYG5v
+LScgdG8gZ2l2ZSB0aGUKb3Bwb3NpdGUgbWVhbmluZy4gVGhlIG9wdGlvbnMgYXJl
+OgoKQHRhYmxlIEBhc2lzCgogIEBpdGVtIGltcG9ydC1sb2NhbC1zaWdzCiAgQWxs
+b3cgaW1wb3J0aW5nIGtleSBzaWduYXR1cmVzIG1hcmtlZCBhcyAibG9jYWwiLiBU
+aGlzIGlzIG5vdAogIGdlbmVyYWxseSB1c2VmdWwgdW5sZXNzIGEgc2hhcmVkIGtl
+eXJpbmcgc2NoZW1lIGlzIGJlaW5nIHVzZWQuCiAgRGVmYXVsdHMgdG8gbm8uCgog
+IEBpdGVtIGtlZXAtb3duZXJ0cnVzdAogIE5vcm1hbGx5IHBvc3NpYmxlIHN0aWxs
+IGV4aXN0aW5nIG93bmVydHJ1c3QgdmFsdWVzIG9mIGEga2V5IGFyZQogIGNsZWFy
+ZWQgaWYgYSBrZXkgaXMgaW1wb3J0ZWQuICBUaGlzIGlzIGluIGdlbmVyYWwgZGVz
+aXJhYmxlIHNvIHRoYXQKICBhIGZvcm1lcmx5IGRlbGV0ZWQga2V5IGRvZXMgbm90
+IGF1dG9tYXRpY2FsbHkgZ2FpbiBhbiBvd25lcnRydXN0CiAgdmFsdWVzIG1lcmVs
+eSBkdWUgdG8gaW1wb3J0LiAgT24gdGhlIG90aGVyIGhhbmQgaXQgaXMgc29tZXRp
+bWVzCiAgbmVjZXNzYXJ5IHRvIHJlLWltcG9ydCBhIHRydXN0ZWQgc2V0IG9mIGtl
+eXMgYWdhaW4gYnV0IGtlZXBpbmcKICBhbHJlYWR5IGFzc2lnbmVkIG93bmVydHJ1
+c3QgdmFsdWVzLiAgVGhpcyBjYW4gYmUgYWNoaXZlZCBieSB1c2luZwogIHRoaXMg
+b3B0aW9uLgoKICBAaXRlbSByZXBhaXItcGtzLXN1YmtleS1idWcKICBEdXJpbmcg
+aW1wb3J0LCBhdHRlbXB0IHRvIHJlcGFpciB0aGUgZGFtYWdlIGNhdXNlZCBieSB0
+aGUgUEtTIGtleXNlcnZlcgogIGJ1ZyAocHJlIHZlcnNpb24gMC45LjYpIHRoYXQg
+bWFuZ2xlcyBrZXlzIHdpdGggbXVsdGlwbGUgc3Via2V5cy4gTm90ZQogIHRoYXQg
+dGhpcyBjYW5ub3QgY29tcGxldGVseSByZXBhaXIgdGhlIGRhbWFnZWQga2V5IGFz
+IHNvbWUgY3J1Y2lhbCBkYXRhCiAgaXMgcmVtb3ZlZCBieSB0aGUga2V5c2VydmVy
+LCBidXQgaXQgZG9lcyBhdCBsZWFzdCBnaXZlIHlvdSBiYWNrIG9uZQogIHN1Ymtl
+eS4gRGVmYXVsdHMgdG8gbm8gZm9yIHJlZ3VsYXIgQG9wdGlvbnstLWltcG9ydH0g
+YW5kIHRvIHllcyBmb3IKICBrZXlzZXJ2ZXIgQG9wdGlvbnstLXJlY3Yta2V5c30u
+CgogIEBpdGVtIG1lcmdlLW9ubHkKICBEdXJpbmcgaW1wb3J0LCBhbGxvdyBrZXkg
+dXBkYXRlcyB0byBleGlzdGluZyBrZXlzLCBidXQgZG8gbm90IGFsbG93CiAgYW55
+IG5ldyBrZXlzIHRvIGJlIGltcG9ydGVkLiBEZWZhdWx0cyB0byBuby4KCiAgQGl0
+ZW0gaW1wb3J0LWNsZWFuCiAgQWZ0ZXIgaW1wb3J0LCBjb21wYWN0IChyZW1vdmUg
+YWxsIHNpZ25hdHVyZXMgZXhjZXB0IHRoZQogIHNlbGYtc2lnbmF0dXJlKSBhbnkg
+dXNlciBJRHMgZnJvbSB0aGUgbmV3IGtleSB0aGF0IGFyZSBub3QgdXNhYmxlLgog
+IFRoZW4sIHJlbW92ZSBhbnkgc2lnbmF0dXJlcyBmcm9tIHRoZSBuZXcga2V5IHRo
+YXQgYXJlIG5vdCB1c2FibGUuCiAgVGhpcyBpbmNsdWRlcyBzaWduYXR1cmVzIHRo
+YXQgd2VyZSBpc3N1ZWQgYnkga2V5cyB0aGF0IGFyZSBub3QgcHJlc2VudAogIG9u
+IHRoZSBrZXlyaW5nLiBUaGlzIG9wdGlvbiBpcyB0aGUgc2FtZSBhcyBydW5uaW5n
+IHRoZSBAb3B0aW9uey0tZWRpdC1rZXl9CiAgY29tbWFuZCAiY2xlYW4iIGFmdGVy
+IGltcG9ydC4gRGVmYXVsdHMgdG8gbm8uCgogIEBpdGVtIGltcG9ydC1taW5pbWFs
+CiAgSW1wb3J0IHRoZSBzbWFsbGVzdCBrZXkgcG9zc2libGUuIFRoaXMgcmVtb3Zl
+cyBhbGwgc2lnbmF0dXJlcyBleGNlcHQKICB0aGUgbW9zdCByZWNlbnQgc2VsZi1z
+aWduYXR1cmUgb24gZWFjaCB1c2VyIElELiBUaGlzIG9wdGlvbiBpcyB0aGUKICBz
+YW1lIGFzIHJ1bm5pbmcgdGhlIEBvcHRpb257LS1lZGl0LWtleX0gY29tbWFuZCAi
+bWluaW1pemUiIGFmdGVyIGltcG9ydC4KICBEZWZhdWx0cyB0byBuby4KQGVuZCB0
+YWJsZQoKQGl0ZW0gLS1leHBvcnQtb3B0aW9ucyBAY29kZXtwYXJhbWV0ZXJzfQpA
+b3BpbmRleCBleHBvcnQtb3B0aW9ucwpUaGlzIGlzIGEgc3BhY2Ugb3IgY29tbWEg
+ZGVsaW1pdGVkIHN0cmluZyB0aGF0IGdpdmVzIG9wdGlvbnMgZm9yCmV4cG9ydGlu
+ZyBrZXlzLiBPcHRpb25zIGNhbiBiZSBwcmVwZW5kZWQgd2l0aCBhIGBuby0nIHRv
+IGdpdmUgdGhlCm9wcG9zaXRlIG1lYW5pbmcuIFRoZSBvcHRpb25zIGFyZToKCkB0
+YWJsZSBAYXNpcwoKICBAaXRlbSBleHBvcnQtbG9jYWwtc2lncwogIEFsbG93IGV4
+cG9ydGluZyBrZXkgc2lnbmF0dXJlcyBtYXJrZWQgYXMgImxvY2FsIi4gVGhpcyBp
+cyBub3QKICBnZW5lcmFsbHkgdXNlZnVsIHVubGVzcyBhIHNoYXJlZCBrZXlyaW5n
+IHNjaGVtZSBpcyBiZWluZyB1c2VkLgogIERlZmF1bHRzIHRvIG5vLgoKICBAaXRl
+bSBleHBvcnQtYXR0cmlidXRlcwogIEluY2x1ZGUgYXR0cmlidXRlIHVzZXIgSURz
+IChwaG90byBJRHMpIHdoaWxlIGV4cG9ydGluZy4gVGhpcyBpcwogIHVzZWZ1bCB0
+byBleHBvcnQga2V5cyBpZiB0aGV5IGFyZSBnb2luZyB0byBiZSB1c2VkIGJ5IGFu
+IE9wZW5QR1AKICBwcm9ncmFtIHRoYXQgZG9lcyBub3QgYWNjZXB0IGF0dHJpYnV0
+ZSB1c2VyIElEcy4gRGVmYXVsdHMgdG8geWVzLgoKICBAaXRlbSBleHBvcnQtc2Vu
+c2l0aXZlLXJldmtleXMKICBJbmNsdWRlIGRlc2lnbmF0ZWQgcmV2b2tlciBpbmZv
+cm1hdGlvbiB0aGF0IHdhcyBtYXJrZWQgYXMKICAic2Vuc2l0aXZlIi4gRGVmYXVs
+dHMgdG8gbm8uCgogIEBjIFNpbmNlIEdudVBHIDIuMSBncGctYWdlbnQgbWFuYWdl
+cyB0aGUgc2VjcmV0IGtleSBhbmQgdGh1cyB0aGUKICBAYyBleHBvcnQtcmVzZXQt
+c3Via2V5LXBhc3N3ZCBoYWNrIGlzIG5vdCBhbnltb3JlIGp1c3RpZmllZC4gIFN1
+Y2ggdXNlCiAgQGMgY2FzZXMgbWF5IGJlIGltcGxlbWVudGVkIHVzaW5nIGEgc3Bl
+Y2lhbGl6ZWQgc2VjcmV0IGtleSBleHBvcnQKICBAYyB0b29sLgogIEBjIEBpdGVt
+IGV4cG9ydC1yZXNldC1zdWJrZXktcGFzc3dkCiAgQGMgV2hlbiB1c2luZyB0aGUg
+QG9wdGlvbnstLWV4cG9ydC1zZWNyZXQtc3Via2V5c30gY29tbWFuZCwgdGhpcyBv
+cHRpb24gcmVzZXRzCiAgQGMgdGhlIHBhc3NwaHJhc2VzIGZvciBhbGwgZXhwb3J0
+ZWQgc3Via2V5cyB0byBlbXB0eS4gVGhpcyBpcyB1c2VmdWwKICBAYyB3aGVuIHRo
+ZSBleHBvcnRlZCBzdWJrZXkgaXMgdG8gYmUgdXNlZCBvbiBhbiB1bmF0dGVuZGVk
+IG1hY2hpbmUgd2hlcmUKICBAYyBhIHBhc3NwaHJhc2UgZG9lc24ndCBuZWNlc3Nh
+cmlseSBtYWtlIHNlbnNlLiBEZWZhdWx0cyB0byBuby4KCiAgQGl0ZW0gZXhwb3J0
+LWNsZWFuCiAgQ29tcGFjdCAocmVtb3ZlIGFsbCBzaWduYXR1cmVzIGZyb20pIHVz
+ZXIgSURzIG9uIHRoZSBrZXkgYmVpbmcKICBleHBvcnRlZCBpZiB0aGUgdXNlciBJ
+RHMgYXJlIG5vdCB1c2FibGUuIEFsc28sIGRvIG5vdCBleHBvcnQgYW55CiAgc2ln
+bmF0dXJlcyB0aGF0IGFyZSBub3QgdXNhYmxlLiBUaGlzIGluY2x1ZGVzIHNpZ25h
+dHVyZXMgdGhhdCB3ZXJlCiAgaXNzdWVkIGJ5IGtleXMgdGhhdCBhcmUgbm90IHBy
+ZXNlbnQgb24gdGhlIGtleXJpbmcuIFRoaXMgb3B0aW9uIGlzCiAgdGhlIHNhbWUg
+YXMgcnVubmluZyB0aGUgQG9wdGlvbnstLWVkaXQta2V5fSBjb21tYW5kICJjbGVh
+biIgYmVmb3JlIGV4cG9ydAogIGV4Y2VwdCB0aGF0IHRoZSBsb2NhbCBjb3B5IG9m
+IHRoZSBrZXkgaXMgbm90IG1vZGlmaWVkLiBEZWZhdWx0cyB0bwogIG5vLgoKICBA
+aXRlbSBleHBvcnQtbWluaW1hbAogIEV4cG9ydCB0aGUgc21hbGxlc3Qga2V5IHBv
+c3NpYmxlLiBUaGlzIHJlbW92ZXMgYWxsIHNpZ25hdHVyZXMgZXhjZXB0IHRoZQog
+IG1vc3QgcmVjZW50IHNlbGYtc2lnbmF0dXJlIG9uIGVhY2ggdXNlciBJRC4gVGhp
+cyBvcHRpb24gaXMgdGhlIHNhbWUgYXMKICBydW5uaW5nIHRoZSBAb3B0aW9uey0t
+ZWRpdC1rZXl9IGNvbW1hbmQgIm1pbmltaXplIiBiZWZvcmUgZXhwb3J0IGV4Y2Vw
+dAogIHRoYXQgdGhlIGxvY2FsIGNvcHkgb2YgdGhlIGtleSBpcyBub3QgbW9kaWZp
+ZWQuIERlZmF1bHRzIHRvIG5vLgpAZW5kIHRhYmxlCgpAaXRlbSAtLXdpdGgtY29s
+b25zCkBvcGluZGV4IHdpdGgtY29sb25zClByaW50IGtleSBsaXN0aW5ncyBkZWxp
+bWl0ZWQgYnkgY29sb25zLiBOb3RlIHRoYXQgdGhlIG91dHB1dCB3aWxsIGJlCmVu
+Y29kZWQgaW4gVVRGLTggcmVnYXJkbGVzcyBvZiBhbnkgQG9wdGlvbnstLWRpc3Bs
+YXktY2hhcnNldH0gc2V0dGluZy4gVGhpcwpmb3JtYXQgaXMgdXNlZnVsIHdoZW4g
+R251UEcgaXMgY2FsbGVkIGZyb20gc2NyaXB0cyBhbmQgb3RoZXIgcHJvZ3JhbXMK
+YXMgaXQgaXMgZWFzaWx5IG1hY2hpbmUgcGFyc2VkLiBUaGUgZGV0YWlscyBvZiB0
+aGlzIGZvcm1hdCBhcmUKZG9jdW1lbnRlZCBpbiB0aGUgZmlsZSBAZmlsZXtkb2Mv
+REVUQUlMU30sIHdoaWNoIGlzIGluY2x1ZGVkIGluIHRoZSBHbnVQRwpzb3VyY2Ug
+ZGlzdHJpYnV0aW9uLgoKCkBpdGVtIC0tcHJpbnQtcGthLXJlY29yZHMKQG9waW5k
+ZXggcHJpbnQtcGthLXJlY29yZHMKTW9kaWZ5IHRoZSBvdXRwdXQgb2YgdGhlIGxp
+c3QgY29tbWFuZHMgdG8gcHJpbnQgUEtBIHJlY29yZHMgc3VpdGFibGUKdG8gcHV0
+IGludG8gRE5TIHpvbmUgZmlsZXMuICBBbiBPUklHSU4gbGluZSBpcyBwcmludGVk
+IGJlZm9yZSBlYWNoCnJlY29yZCB0byBhbGxvdyBkaXZlcnRpbmcgdGhlIHJlY29y
+ZHMgdG8gdGhlIGNvcnJlc3BvbmRpbmcgem9uZSBmaWxlLgoKQGl0ZW0gLS1wcmlu
+dC1kYW5lLXJlY29yZHMKQG9waW5kZXggcHJpbnQtZGFuZS1yZWNvcmRzCk1vZGlm
+eSB0aGUgb3V0cHV0IG9mIHRoZSBsaXN0IGNvbW1hbmRzIHRvIHByaW50IE9wZW5Q
+R1AgREFORSByZWNvcmRzCnN1aXRhYmxlIHRvIHB1dCBpbnRvIEROUyB6b25lIGZp
+bGVzLiAgQW4gT1JJR0lOIGxpbmUgaXMgcHJpbnRlZCBiZWZvcmUKZWFjaCByZWNv
+cmQgdG8gYWxsb3cgZGl2ZXJ0aW5nIHRoZSByZWNvcmRzIHRvIHRoZSBjb3JyZXNw
+b25kaW5nIHpvbmUKZmlsZS4KCkBpdGVtIC0tZml4ZWQtbGlzdC1tb2RlCkBvcGlu
+ZGV4IGZpeGVkLWxpc3QtbW9kZQpEbyBub3QgbWVyZ2UgcHJpbWFyeSB1c2VyIElE
+IGFuZCBwcmltYXJ5IGtleSBpbiBAb3B0aW9uey0td2l0aC1jb2xvbn0KbGlzdGlu
+ZyBtb2RlIGFuZCBwcmludCBhbGwgdGltZXN0YW1wcyBhcyBzZWNvbmRzIHNpbmNl
+IDE5NzAtMDEtMDEuClNpbmNlIEdudVBHIDIuMC4xMCwgdGhpcyBtb2RlIGlzIGFs
+d2F5cyB1c2VkIGFuZCB0aHVzIHRoaXMgb3B0aW9uIGlzCm9ic29sZXRlOyBpdCBk
+b2VzIG5vdCBoYXJtIHRvIHVzZSBpdCB0aG91Z2guCgpAaXRlbSAtLWxlZ2FjeS1s
+aXN0LW1vZGUKQG9waW5kZXggbGVnYWN5LWxpc3QtbW9kZQpSZXZlcnQgdG8gdGhl
+IHByZS0yLjEgcHVibGljIGtleSBsaXN0IG1vZGUuICBUaGlzIG9ubHkgYWZmZWN0
+cyB0aGUKaHVtYW4gcmVhZGFibGUgb3V0cHV0IGFuZCBub3QgdGhlIG1hY2hpbmUg
+aW50ZXJmYWNlCihpLmUuIEBjb2Rley0td2l0aC1jb2xvbnN9KS4gIE5vdGUgdGhh
+dCB0aGUgbGVnYWN5IGZvcm1hdCBkb2VzIG5vdAphbGxvdyB0byBjb252ZXkgc3Vp
+dGFibGUgaW5mb3JtYXRpb24gZm9yIGVsbGlwdGljIGN1cnZlcy4KCkBpdGVtIC0t
+d2l0aC1maW5nZXJwcmludApAb3BpbmRleCB3aXRoLWZpbmdlcnByaW50ClNhbWUg
+YXMgdGhlIGNvbW1hbmQgQG9wdGlvbnstLWZpbmdlcnByaW50fSBidXQgY2hhbmdl
+cyBvbmx5IHRoZSBmb3JtYXQKb2YgdGhlIG91dHB1dCBhbmQgbWF5IGJlIHVzZWQg
+dG9nZXRoZXIgd2l0aCBhbm90aGVyIGNvbW1hbmQuCgpAaXRlbSAtLXdpdGgtaWNh
+by1zcGVsbGluZwpAb3BpbmRleCB3aXRoLWljYW8tc3BlbGxpbmcKUHJpbnQgdGhl
+IElDQU8gc3BlbGxpbmcgb2YgdGhlIGZpbmdlcnByaW50IGluIGFkZGl0aW9uIHRv
+IHRoZSBoZXggZGlnaXRzLgoKQGl0ZW0gLS13aXRoLWtleWdyaXAKQG9waW5kZXgg
+d2l0aC1rZXlncmlwCkluY2x1ZGUgdGhlIGtleWdyaXAgaW4gdGhlIGtleSBsaXN0
+aW5ncy4KCkBpdGVtIC0td2l0aC1zZWNyZXQKQG9waW5kZXggd2l0aC1zZWNyZXQK
+SW5jbHVkZSBpbmZvIGFib3V0IHRoZSBwcmVzZW5jZSBvZiBhIHNlY3JldCBrZXkg
+aW4gcHVibGljIGtleSBsaXN0aW5ncwpkb25lIHdpdGggQGNvZGV7LS13aXRoLWNv
+bG9uc30uCgpAZW5kIHRhYmxlCgpAYyAqKioqKioqKioqKioqKioqKioqKioqKioq
+KioqKioqKioqKioqKioqKioqCkBjICoqKioqKioqICBPUEVOUEdQIE9QVElPTlMg
+ICoqKioqKioqKioqKioqKioKQGMgKioqKioqKioqKioqKioqKioqKioqKioqKioq
+KioqKioqKioqKioqKioqKgpAbm9kZSBPcGVuUEdQIE9wdGlvbnMKQHN1YnNlY3Rp
+b24gT3BlblBHUCBwcm90b2NvbCBzcGVjaWZpYyBvcHRpb25zLgoKQHRhYmxlIEBn
+bnVwZ3RhYm9wdAoKQGl0ZW0gLXQsIC0tdGV4dG1vZGUKQGl0ZW14IC0tbm8tdGV4
+dG1vZGUKQG9waW5kZXggdGV4dG1vZGUKVHJlYXQgaW5wdXQgZmlsZXMgYXMgdGV4
+dCBhbmQgc3RvcmUgdGhlbSBpbiB0aGUgT3BlblBHUCBjYW5vbmljYWwgdGV4dApm
+b3JtIHdpdGggc3RhbmRhcmQgIkNSTEYiIGxpbmUgZW5kaW5ncy4gVGhpcyBhbHNv
+IHNldHMgdGhlIG5lY2Vzc2FyeQpmbGFncyB0byBpbmZvcm0gdGhlIHJlY2lwaWVu
+dCB0aGF0IHRoZSBlbmNyeXB0ZWQgb3Igc2lnbmVkIGRhdGEgaXMgdGV4dAphbmQg
+bWF5IG5lZWQgaXRzIGxpbmUgZW5kaW5ncyBjb252ZXJ0ZWQgYmFjayB0byB3aGF0
+ZXZlciB0aGUgbG9jYWwKc3lzdGVtIHVzZXMuIFRoaXMgb3B0aW9uIGlzIHVzZWZ1
+bCB3aGVuIGNvbW11bmljYXRpbmcgYmV0d2VlbiB0d28KcGxhdGZvcm1zIHRoYXQg
+aGF2ZSBkaWZmZXJlbnQgbGluZSBlbmRpbmcgY29udmVudGlvbnMgKFVOSVgtbGlr
+ZSB0byBNYWMsCk1hYyB0byBXaW5kb3dzLCBldGMpLiBAb3B0aW9uey0tbm8tdGV4
+dG1vZGV9IGRpc2FibGVzIHRoaXMgb3B0aW9uLCBhbmQKaXMgdGhlIGRlZmF1bHQu
+CgpAaXRlbSAtLWZvcmNlLXYzLXNpZ3MKQGl0ZW14IC0tbm8tZm9yY2UtdjMtc2ln
+cwpAaXRlbSAtLWZvcmNlLXY0LWNlcnRzCkBpdGVteCAtLW5vLWZvcmNlLXY0LWNl
+cnRzClRoZXNlIG9wdGlvbnMgYXJlIG9ic29sZXRlIGFuZCBoYXZlIG5vIGVmZmVj
+dCBzaW5jZSBHbnVQRyAyLjEuCgpAaXRlbSAtLWZvcmNlLW1kYwpAb3BpbmRleCBm
+b3JjZS1tZGMKRm9yY2UgdGhlIHVzZSBvZiBlbmNyeXB0aW9uIHdpdGggYSBtb2Rp
+ZmljYXRpb24gZGV0ZWN0aW9uIGNvZGUuIFRoaXMKaXMgYWx3YXlzIHVzZWQgd2l0
+aCB0aGUgbmV3ZXIgY2lwaGVycyAodGhvc2Ugd2l0aCBhIGJsb2Nrc2l6ZSBncmVh
+dGVyCnRoYW4gNjQgYml0cyksIG9yIGlmIGFsbCBvZiB0aGUgcmVjaXBpZW50IGtl
+eXMgaW5kaWNhdGUgTURDIHN1cHBvcnQgaW4KdGhlaXIgZmVhdHVyZSBmbGFncy4K
+CkBpdGVtIC0tZGlzYWJsZS1tZGMKQG9waW5kZXggZGlzYWJsZS1tZGMKRGlzYWJs
+ZSB0aGUgdXNlIG9mIHRoZSBtb2RpZmljYXRpb24gZGV0ZWN0aW9uIGNvZGUuIE5v
+dGUgdGhhdCBieQp1c2luZyB0aGlzIG9wdGlvbiwgdGhlIGVuY3J5cHRlZCBtZXNz
+YWdlIGJlY29tZXMgdnVsbmVyYWJsZSB0byBhCm1lc3NhZ2UgbW9kaWZpY2F0aW9u
+IGF0dGFjay4KCkBpdGVtIC0tcGVyc29uYWwtY2lwaGVyLXByZWZlcmVuY2VzIEBj
+b2Rle3N0cmluZ30KQG9waW5kZXggcGVyc29uYWwtY2lwaGVyLXByZWZlcmVuY2Vz
+ClNldCB0aGUgbGlzdCBvZiBwZXJzb25hbCBjaXBoZXIgcHJlZmVyZW5jZXMgdG8g
+QGNvZGV7c3RyaW5nfS4gIFVzZQpAY29tbWFuZHtAZ3BnbmFtZSAtLXZlcnNpb259
+IHRvIGdldCBhIGxpc3Qgb2YgYXZhaWxhYmxlIGFsZ29yaXRobXMsCmFuZCB1c2Ug
+QGNvZGV7bm9uZX0gdG8gc2V0IG5vIHByZWZlcmVuY2UgYXQgYWxsLiAgVGhpcyBh
+bGxvd3MgdGhlIHVzZXIKdG8gc2FmZWx5IG92ZXJyaWRlIHRoZSBhbGdvcml0aG0g
+Y2hvc2VuIGJ5IHRoZSByZWNpcGllbnQga2V5CnByZWZlcmVuY2VzLCBhcyBHUEcg
+d2lsbCBvbmx5IHNlbGVjdCBhbiBhbGdvcml0aG0gdGhhdCBpcyB1c2FibGUgYnkK
+YWxsIHJlY2lwaWVudHMuICBUaGUgbW9zdCBoaWdobHkgcmFua2VkIGNpcGhlciBp
+biB0aGlzIGxpc3QgaXMgYWxzbwp1c2VkIGZvciB0aGUgQG9wdGlvbnstLXN5bW1l
+dHJpY30gZW5jcnlwdGlvbiBjb21tYW5kLgoKQGl0ZW0gLS1wZXJzb25hbC1kaWdl
+c3QtcHJlZmVyZW5jZXMgQGNvZGV7c3RyaW5nfQpAb3BpbmRleCBwZXJzb25hbC1k
+aWdlc3QtcHJlZmVyZW5jZXMKU2V0IHRoZSBsaXN0IG9mIHBlcnNvbmFsIGRpZ2Vz
+dCBwcmVmZXJlbmNlcyB0byBAY29kZXtzdHJpbmd9LiAgVXNlCkBjb21tYW5ke0Bn
+cGduYW1lIC0tdmVyc2lvbn0gdG8gZ2V0IGEgbGlzdCBvZiBhdmFpbGFibGUgYWxn
+b3JpdGhtcywKYW5kIHVzZSBAY29kZXtub25lfSB0byBzZXQgbm8gcHJlZmVyZW5j
+ZSBhdCBhbGwuICBUaGlzIGFsbG93cyB0aGUgdXNlcgp0byBzYWZlbHkgb3ZlcnJp
+ZGUgdGhlIGFsZ29yaXRobSBjaG9zZW4gYnkgdGhlIHJlY2lwaWVudCBrZXkKcHJl
+ZmVyZW5jZXMsIGFzIEdQRyB3aWxsIG9ubHkgc2VsZWN0IGFuIGFsZ29yaXRobSB0
+aGF0IGlzIHVzYWJsZSBieQphbGwgcmVjaXBpZW50cy4gIFRoZSBtb3N0IGhpZ2hs
+eSByYW5rZWQgZGlnZXN0IGFsZ29yaXRobSBpbiB0aGlzIGxpc3QKaXMgYWxzbyB1
+c2VkIHdoZW4gc2lnbmluZyB3aXRob3V0IGVuY3J5cHRpb24KKGUuZy4gQG9wdGlv
+bnstLWNsZWFyc2lnbn0gb3IgQG9wdGlvbnstLXNpZ259KS4KCkBpdGVtIC0tcGVy
+c29uYWwtY29tcHJlc3MtcHJlZmVyZW5jZXMgQGNvZGV7c3RyaW5nfQpAb3BpbmRl
+eCBwZXJzb25hbC1jb21wcmVzcy1wcmVmZXJlbmNlcwpTZXQgdGhlIGxpc3Qgb2Yg
+cGVyc29uYWwgY29tcHJlc3Npb24gcHJlZmVyZW5jZXMgdG8gQGNvZGV7c3RyaW5n
+fS4KVXNlIEBjb21tYW5ke0BncGduYW1lIC0tdmVyc2lvbn0gdG8gZ2V0IGEgbGlz
+dCBvZiBhdmFpbGFibGUKYWxnb3JpdGhtcywgYW5kIHVzZSBAY29kZXtub25lfSB0
+byBzZXQgbm8gcHJlZmVyZW5jZSBhdCBhbGwuICBUaGlzCmFsbG93cyB0aGUgdXNl
+ciB0byBzYWZlbHkgb3ZlcnJpZGUgdGhlIGFsZ29yaXRobSBjaG9zZW4gYnkgdGhl
+CnJlY2lwaWVudCBrZXkgcHJlZmVyZW5jZXMsIGFzIEdQRyB3aWxsIG9ubHkgc2Vs
+ZWN0IGFuIGFsZ29yaXRobSB0aGF0CmlzIHVzYWJsZSBieSBhbGwgcmVjaXBpZW50
+cy4gIFRoZSBtb3N0IGhpZ2hseSByYW5rZWQgY29tcHJlc3Npb24KYWxnb3JpdGht
+IGluIHRoaXMgbGlzdCBpcyBhbHNvIHVzZWQgd2hlbiB0aGVyZSBhcmUgbm8gcmVj
+aXBpZW50IGtleXMKdG8gY29uc2lkZXIgKGUuZy4gQG9wdGlvbnstLXN5bW1ldHJp
+Y30pLgoKQGl0ZW0gLS1zMmstY2lwaGVyLWFsZ28gQGNvZGV7bmFtZX0KQG9waW5k
+ZXggczJrLWNpcGhlci1hbGdvClVzZSBAY29kZXtuYW1lfSBhcyB0aGUgY2lwaGVy
+IGFsZ29yaXRobSB1c2VkIHRvIHByb3RlY3Qgc2VjcmV0IGtleXMuClRoZSBkZWZh
+dWx0IGNpcGhlciBpcyBAdmFsdWV7R1BHU1lNRU5DQUxHT30uIFRoaXMgY2lwaGVy
+IGlzIGFsc28gdXNlZApmb3Igc3ltbWV0cmljIGVuY3J5cHRpb24gd2l0aCBhIHBh
+c3NwaHJhc2UgaWYKQG9wdGlvbnstLXBlcnNvbmFsLWNpcGhlci1wcmVmZXJlbmNl
+c30gYW5kIEBvcHRpb257LS1jaXBoZXItYWxnb30gaXMKbm90IGdpdmVuLgoKQGl0
+ZW0gLS1zMmstZGlnZXN0LWFsZ28gQGNvZGV7bmFtZX0KQG9waW5kZXggczJrLWRp
+Z2VzdC1hbGdvClVzZSBAY29kZXtuYW1lfSBhcyB0aGUgZGlnZXN0IGFsZ29yaXRo
+bSB1c2VkIHRvIG1hbmdsZSB0aGUgcGFzc3BocmFzZXMuClRoZSBkZWZhdWx0IGFs
+Z29yaXRobSBpcyBTSEEtMS4KCkBpdGVtIC0tczJrLW1vZGUgQGNvZGV7bn0KQG9w
+aW5kZXggczJrLW1vZGUKU2VsZWN0cyBob3cgcGFzc3BocmFzZXMgYXJlIG1hbmds
+ZWQuIElmIEBjb2Rle259IGlzIDAgYSBwbGFpbgpwYXNzcGhyYXNlICh3aGljaCBp
+cyBub3QgcmVjb21tZW5kZWQpIHdpbGwgYmUgdXNlZCwgYSAxIGFkZHMgYSBzYWx0
+IHRvCnRoZSBwYXNzcGhyYXNlIGFuZCBhIDMgKHRoZSBkZWZhdWx0KSBpdGVyYXRl
+cyB0aGUgd2hvbGUgcHJvY2VzcyBhCm51bWJlciBvZiB0aW1lcyAoc2VlIC0tczJr
+LWNvdW50KS4gIFVubGVzcyBAb3B0aW9uey0tcmZjMTk5MX0gaXMgdXNlZCwKdGhp
+cyBtb2RlIGlzIGFsc28gdXNlZCBmb3Igc3ltbWV0cmljIGVuY3J5cHRpb24gd2l0
+aCBhIHBhc3NwaHJhc2UuCgpAaXRlbSAtLXMyay1jb3VudCBAY29kZXtufQpAb3Bp
+bmRleCBzMmstY291bnQKU3BlY2lmeSBob3cgbWFueSB0aW1lcyB0aGUgcGFzc3Bo
+cmFzZSBtYW5nbGluZyBpcyByZXBlYXRlZC4gIFRoaXMKdmFsdWUgbWF5IHJhbmdl
+IGJldHdlZW4gMTAyNCBhbmQgNjUwMTE3MTIgaW5jbHVzaXZlLiAgVGhlIGRlZmF1
+bHQgaXMKaW5xdWlyZWQgZnJvbSBncGctYWdlbnQuICBOb3RlIHRoYXQgbm90IGFs
+bCB2YWx1ZXMgaW4gdGhlCjEwMjQtNjUwMTE3MTIgcmFuZ2UgYXJlIGxlZ2FsIGFu
+ZCBpZiBhbiBpbGxlZ2FsIHZhbHVlIGlzIHNlbGVjdGVkLApHbnVQRyB3aWxsIHJv
+dW5kIHVwIHRvIHRoZSBuZWFyZXN0IGxlZ2FsIHZhbHVlLiAgVGhpcyBvcHRpb24g
+aXMgb25seQptZWFuaW5nZnVsIGlmIEBvcHRpb257LS1zMmstbW9kZX0gaXMgMy4K
+CgpAZW5kIHRhYmxlCgpAYyAqKioqKioqKioqKioqKioqKioqKioqKioqKioKQGMg
+KioqKioqKiBDb21wbGlhbmNlICoqKioqKioqCkBjICoqKioqKioqKioqKioqKioq
+KioqKioqKioqKgpAbm9kZSBDb21wbGlhbmNlIE9wdGlvbnMKQHN1YnNlY3Rpb24g
+Q29tcGxpYW5jZSBvcHRpb25zCgpUaGVzZSBvcHRpb25zIGNvbnRyb2wgd2hhdCBH
+bnVQRyBpcyBjb21wbGlhbnQgdG8uIE9ubHkgb25lIG9mIHRoZXNlCm9wdGlvbnMg
+bWF5IGJlIGFjdGl2ZSBhdCBhIHRpbWUuIE5vdGUgdGhhdCB0aGUgZGVmYXVsdCBz
+ZXR0aW5nIG9mCnRoaXMgaXMgbmVhcmx5IGFsd2F5cyB0aGUgY29ycmVjdCBvbmUu
+IFNlZSB0aGUgSU5URVJPUEVSQUJJTElUWSBXSVRICk9USEVSIE9QRU5QR1AgUFJP
+R1JBTVMgc2VjdGlvbiBiZWxvdyBiZWZvcmUgdXNpbmcgb25lIG9mIHRoZXNlCm9w
+dGlvbnMuCgpAdGFibGUgQGdudXBndGFib3B0CgpAaXRlbSAtLWdudXBnCkBvcGlu
+ZGV4IGdudXBnClVzZSBzdGFuZGFyZCBHbnVQRyBiZWhhdmlvci4gVGhpcyBpcyBl
+c3NlbnRpYWxseSBPcGVuUEdQIGJlaGF2aW9yCihzZWUgQG9wdGlvbnstLW9wZW5w
+Z3B9KSwgYnV0IHdpdGggc29tZSBhZGRpdGlvbmFsIHdvcmthcm91bmRzIGZvciBj
+b21tb24KY29tcGF0aWJpbGl0eSBwcm9ibGVtcyBpbiBkaWZmZXJlbnQgdmVyc2lv
+bnMgb2YgUEdQLiBUaGlzIGlzIHRoZQpkZWZhdWx0IG9wdGlvbiwgc28gaXQgaXMg
+bm90IGdlbmVyYWxseSBuZWVkZWQsIGJ1dCBpdCBtYXkgYmUgdXNlZnVsIHRvCm92
+ZXJyaWRlIGEgZGlmZmVyZW50IGNvbXBsaWFuY2Ugb3B0aW9uIGluIHRoZSBncGcu
+Y29uZiBmaWxlLgoKQGl0ZW0gLS1vcGVucGdwCkBvcGluZGV4IG9wZW5wZ3AKUmVz
+ZXQgYWxsIHBhY2tldCwgY2lwaGVyIGFuZCBkaWdlc3Qgb3B0aW9ucyB0byBzdHJp
+Y3QgT3BlblBHUApiZWhhdmlvci4gVXNlIHRoaXMgb3B0aW9uIHRvIHJlc2V0IGFs
+bCBwcmV2aW91cyBvcHRpb25zIGxpa2UKQG9wdGlvbnstLXMyay0qfSwgQG9wdGlv
+bnstLWNpcGhlci1hbGdvfSwgQG9wdGlvbnstLWRpZ2VzdC1hbGdvfSBhbmQKQG9w
+dGlvbnstLWNvbXByZXNzLWFsZ299IHRvIE9wZW5QR1AgY29tcGxpYW50IHZhbHVl
+cy4gQWxsIFBHUAp3b3JrYXJvdW5kcyBhcmUgZGlzYWJsZWQuCgpAaXRlbSAtLXJm
+YzQ4ODAKQG9waW5kZXggcmZjNDg4MApSZXNldCBhbGwgcGFja2V0LCBjaXBoZXIg
+YW5kIGRpZ2VzdCBvcHRpb25zIHRvIHN0cmljdCBSRkMtNDg4MApiZWhhdmlvci4g
+Tm90ZSB0aGF0IHRoaXMgaXMgY3VycmVudGx5IHRoZSBzYW1lIHRoaW5nIGFzCkBv
+cHRpb257LS1vcGVucGdwfS4KCkBpdGVtIC0tcmZjMjQ0MApAb3BpbmRleCByZmMy
+NDQwClJlc2V0IGFsbCBwYWNrZXQsIGNpcGhlciBhbmQgZGlnZXN0IG9wdGlvbnMg
+dG8gc3RyaWN0IFJGQy0yNDQwCmJlaGF2aW9yLgoKQGlmY2xlYXIgZ3BndG93b25l
+CkBpdGVtIC0tcmZjMTk5MQpAb3BpbmRleCByZmMxOTkxClRyeSB0byBiZSBtb3Jl
+IFJGQy0xOTkxIChQR1AgMi54KSBjb21wbGlhbnQuICBUaGlzIG9wdGlvbiBpcwpk
+ZXByZWNhdGVkIHdpbGwgYmUgcmVtb3ZlZCBpbiBHbnVQRyAyLjEuCgpAaXRlbSAt
+LXBncDIKQG9waW5kZXggcGdwMgpTZXQgdXAgYWxsIG9wdGlvbnMgdG8gYmUgYXMg
+UEdQIDIueCBjb21wbGlhbnQgYXMgcG9zc2libGUsIGFuZCB3YXJuIGlmCmFuIGFj
+dGlvbiBpcyB0YWtlbiAoZS5nLiBlbmNyeXB0aW5nIHRvIGEgbm9uLVJTQSBrZXkp
+IHRoYXQgd2lsbCBjcmVhdGUKYSBtZXNzYWdlIHRoYXQgUEdQIDIueCB3aWxsIG5v
+dCBiZSBhYmxlIHRvIGhhbmRsZS4gTm90ZSB0aGF0IGBQR1AKMi54JyBoZXJlIG1l
+YW5zIGBNSVQgUEdQIDIuNi4yJy4gVGhlcmUgYXJlIG90aGVyIHZlcnNpb25zIG9m
+IFBHUCAyLngKYXZhaWxhYmxlLCBidXQgdGhlIE1JVCByZWxlYXNlIGlzIGEgZ29v
+ZCBjb21tb24gYmFzZWxpbmUuCgpUaGlzIG9wdGlvbiBpbXBsaWVzCkBvcHRpb257
+LS1yZmMxOTkxIC0tZGlzYWJsZS1tZGMgLS1uby1mb3JjZS12NC1jZXJ0cwogLS1l
+c2NhcGUtZnJvbS1saW5lcyAgLS1mb3JjZS12My1zaWdzIC0tYWxsb3ctd2Vhay1k
+aWdlc3QtYWxnb3MKIC0tY2lwaGVyLWFsZ28gSURFQSAtLWRpZ2VzdC1hbGdvIE1E
+NSAtLWNvbXByZXNzLWFsZ28gWklQfS4KSXQgYWxzbyBkaXNhYmxlcyBAb3B0aW9u
+ey0tdGV4dG1vZGV9IHdoZW4gZW5jcnlwdGluZy4KClRoaXMgb3B0aW9uIGlzIGRl
+cHJlY2F0ZWQgd2lsbCBiZSByZW1vdmVkIGluIEdudVBHIDIuMS4gIFRoZSByZWFz
+b24KZm9yIGRyb3BwaW5nIFBHUC0yIHN1cHBvcnQgaXMgdGhhdCB0aGUgUEdQIDIg
+Zm9ybWF0IGlzIG5vdCBhbnltb3JlCmNvbnNpZGVyZWQgc2FmZSAoZm9yIGV4YW1w
+bGUgZHVlIHRvIHRoZSB1c2Ugb2YgdGhlIGJyb2tlbiBNRDUgYWxnb3JpdGhtKS4K
+Tm90ZSB0aGF0IHRoZSBkZWNyeXB0aW9uIG9mIFBHUC0yIGNyZWF0ZWQgbWVzc2Fn
+ZXMgd2lsbCBjb250aW51ZSB0byB3b3JrLgpAZW5kIGlmY2xlYXIKCkBpdGVtIC0t
+cGdwNgpAb3BpbmRleCBwZ3A2ClNldCB1cCBhbGwgb3B0aW9ucyB0byBiZSBhcyBQ
+R1AgNiBjb21wbGlhbnQgYXMgcG9zc2libGUuIFRoaXMKcmVzdHJpY3RzIHlvdSB0
+byB0aGUgY2lwaGVycyBJREVBIChpZiB0aGUgSURFQSBwbHVnaW4gaXMgaW5zdGFs
+bGVkKSwKM0RFUywgYW5kIENBU1Q1LCB0aGUgaGFzaGVzIE1ENSwgU0hBMSBhbmQg
+UklQRU1EMTYwLCBhbmQgdGhlCmNvbXByZXNzaW9uIGFsZ29yaXRobXMgbm9uZSBh
+bmQgWklQLiBUaGlzIGFsc28gZGlzYWJsZXMKLS10aHJvdy1rZXlpZHMsIGFuZCBt
+YWtpbmcgc2lnbmF0dXJlcyB3aXRoIHNpZ25pbmcgc3Via2V5cyBhcyBQR1AgNgpk
+b2VzIG5vdCB1bmRlcnN0YW5kIHNpZ25hdHVyZXMgbWFkZSBieSBzaWduaW5nIHN1
+YmtleXMuCgpUaGlzIG9wdGlvbiBpbXBsaWVzIEBvcHRpb257LS1kaXNhYmxlLW1k
+YyAtLWVzY2FwZS1mcm9tLWxpbmVzfS4KCkBpdGVtIC0tcGdwNwpAb3BpbmRleCBw
+Z3A3ClNldCB1cCBhbGwgb3B0aW9ucyB0byBiZSBhcyBQR1AgNyBjb21wbGlhbnQg
+YXMgcG9zc2libGUuIFRoaXMgaXMKaWRlbnRpY2FsIHRvIEBvcHRpb257LS1wZ3A2
+fSBleGNlcHQgdGhhdCBNRENzIGFyZSBub3QgZGlzYWJsZWQsIGFuZCB0aGUKbGlz
+dCBvZiBhbGxvd2FibGUgY2lwaGVycyBpcyBleHBhbmRlZCB0byBhZGQgQUVTMTI4
+LCBBRVMxOTIsIEFFUzI1NiwgYW5kClRXT0ZJU0guCgpAaXRlbSAtLXBncDgKQG9w
+aW5kZXggcGdwOApTZXQgdXAgYWxsIG9wdGlvbnMgdG8gYmUgYXMgUEdQIDggY29t
+cGxpYW50IGFzIHBvc3NpYmxlLiBQR1AgOCBpcyBhIGxvdApjbG9zZXIgdG8gdGhl
+IE9wZW5QR1Agc3RhbmRhcmQgdGhhbiBwcmV2aW91cyB2ZXJzaW9ucyBvZiBQR1As
+IHNvIGFsbAp0aGlzIGRvZXMgaXMgZGlzYWJsZSBAb3B0aW9uey0tdGhyb3cta2V5
+aWRzfSBhbmQgc2V0CkBvcHRpb257LS1lc2NhcGUtZnJvbS1saW5lc30uICBBbGwg
+YWxnb3JpdGhtcyBhcmUgYWxsb3dlZCBleGNlcHQgZm9yIHRoZQpTSEEyMjQsIFNI
+QTM4NCwgYW5kIFNIQTUxMiBkaWdlc3RzLgoKQGVuZCB0YWJsZQoKCkBjICoqKioq
+KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKQGMgKioqKioq
+KiogIEVTT1RFUklDIE9QVElPTlMgICoqKioqKioqKioqKioqKgpAYyAqKioqKioq
+KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCkBub2RlIEdQRyBF
+c290ZXJpYyBPcHRpb25zCkBzdWJzZWN0aW9uIERvaW5nIHRoaW5ncyBvbmUgdXN1
+YWxseSBkb2Vzbid0IHdhbnQgdG8gZG8uCgpAdGFibGUgQGdudXBndGFib3B0CgpA
+aXRlbSAtbgpAaXRlbXggLS1kcnktcnVuCkBvcGluZGV4IGRyeS1ydW4KRG9uJ3Qg
+bWFrZSBhbnkgY2hhbmdlcyAodGhpcyBpcyBub3QgY29tcGxldGVseSBpbXBsZW1l
+bnRlZCkuCgpAaXRlbSAtLWxpc3Qtb25seQpAb3BpbmRleCBsaXN0LW9ubHkKQ2hh
+bmdlcyB0aGUgYmVoYXZpb3VyIG9mIHNvbWUgY29tbWFuZHMuIFRoaXMgaXMgbGlr
+ZSBAb3B0aW9uey0tZHJ5LXJ1bn0gYnV0CmRpZmZlcmVudCBpbiBzb21lIGNhc2Vz
+LiBUaGUgc2VtYW50aWMgb2YgdGhpcyBjb21tYW5kIG1heSBiZSBleHRlbmRlZCBp
+bgp0aGUgZnV0dXJlLiBDdXJyZW50bHkgaXQgb25seSBza2lwcyB0aGUgYWN0dWFs
+IGRlY3J5cHRpb24gcGFzcyBhbmQKdGhlcmVmb3JlIGVuYWJsZXMgYSBmYXN0IGxp
+c3Rpbmcgb2YgdGhlIGVuY3J5cHRpb24ga2V5cy4KCkBpdGVtIC1pCkBpdGVteCAt
+LWludGVyYWN0aXZlCkBvcGluZGV4IGludGVyYWN0aXZlClByb21wdCBiZWZvcmUg
+b3ZlcndyaXRpbmcgYW55IGZpbGVzLgoKQGl0ZW0gLS1kZWJ1Zy1sZXZlbCBAdmFy
+e2xldmVsfQpAb3BpbmRleCBkZWJ1Zy1sZXZlbApTZWxlY3QgdGhlIGRlYnVnIGxl
+dmVsIGZvciBpbnZlc3RpZ2F0aW5nIHByb2JsZW1zLiBAdmFye2xldmVsfSBtYXkg
+YmUKYSBudW1lcmljIHZhbHVlIG9yIGJ5IGEga2V5d29yZDoKCkB0YWJsZSBAY29k
+ZQogIEBpdGVtIG5vbmUKICBObyBkZWJ1Z2dpbmcgYXQgYWxsLiAgQSB2YWx1ZSBv
+ZiBsZXNzIHRoYW4gMSBtYXkgYmUgdXNlZCBpbnN0ZWFkIG9mCiAgdGhlIGtleXdv
+cmQuCiAgQGl0ZW0gYmFzaWMKICBTb21lIGJhc2ljIGRlYnVnIG1lc3NhZ2VzLiAg
+QSB2YWx1ZSBiZXR3ZWVuIDEgYW5kIDIgbWF5IGJlIHVzZWQKICBpbnN0ZWFkIG9m
+IHRoZSBrZXl3b3JkLgogIEBpdGVtIGFkdmFuY2VkCiAgTW9yZSB2ZXJib3NlIGRl
+YnVnIG1lc3NhZ2VzLiAgQSB2YWx1ZSBiZXR3ZWVuIDMgYW5kIDUgbWF5IGJlIHVz
+ZWQKICBpbnN0ZWFkIG9mIHRoZSBrZXl3b3JkLgogIEBpdGVtIGV4cGVydAogIEV2
+ZW4gbW9yZSBkZXRhaWxlZCBtZXNzYWdlcy4gIEEgdmFsdWUgYmV0d2VlbiA2IGFu
+ZCA4IG1heSBiZSB1c2VkCiAgaW5zdGVhZCBvZiB0aGUga2V5d29yZC4KICBAaXRl
+bSBndXJ1CiAgQWxsIG9mIHRoZSBkZWJ1ZyBtZXNzYWdlcyB5b3UgY2FuIGdldC4g
+QSB2YWx1ZSBncmVhdGVyIHRoYW4gOCBtYXkgYmUKICB1c2VkIGluc3RlYWQgb2Yg
+dGhlIGtleXdvcmQuICBUaGUgY3JlYXRpb24gb2YgaGFzaCB0cmFjaW5nIGZpbGVz
+IGlzCiAgb25seSBlbmFibGVkIGlmIHRoZSBrZXl3b3JkIGlzIHVzZWQuCkBlbmQg
+dGFibGUKCkhvdyB0aGVzZSBtZXNzYWdlcyBhcmUgbWFwcGVkIHRvIHRoZSBhY3R1
+YWwgZGVidWdnaW5nIGZsYWdzIGlzIG5vdApzcGVjaWZpZWQgYW5kIG1heSBjaGFu
+Z2Ugd2l0aCBuZXdlciByZWxlYXNlcyBvZiB0aGlzIHByb2dyYW0uIFRoZXkgYXJl
+Cmhvd2V2ZXIgY2FyZWZ1bGx5IHNlbGVjdGVkIHRvIGJlc3QgYWlkIGluIGRlYnVn
+Z2luZy4KCkBpdGVtIC0tZGVidWcgQHZhcntmbGFnc30KQG9waW5kZXggZGVidWcK
+U2V0IGRlYnVnZ2luZyBmbGFncy4gQWxsIGZsYWdzIGFyZSBvci1lZCBhbmQgQHZh
+cntmbGFnc30gbWF5IGJlIGdpdmVuCmluIEMgc3ludGF4IChlLmcuIDB4MDA0Mikg
+b3IgYXMgYSBjb21tYSBzZXBhcmF0ZWQgbGlzdCBvZiBmbGFnIG5hbWVzLgpUbyBn
+ZXQgYSBsaXN0IG9mIGFsbCBzdXBwb3J0ZWQgZmxhZ3MgdGhlIHNpbmdsZSB3b3Jk
+ICJoZWxwIiBjYW4gYmUKdXNlZC4KCkBpdGVtIC0tZGVidWctYWxsCkBvcGluZGV4
+IGRlYnVnLWFsbApTZXQgYWxsIHVzZWZ1bCBkZWJ1Z2dpbmcgZmxhZ3MuCgpAaXRl
+bSAtLWRlYnVnLWlvbGJmCkBvcGluZGV4IGRlYnVnLWlvbGJmClNldCBzdGRvdXQg
+aW50byBsaW5lIGJ1ZmZlcmVkIG1vZGUuICBUaGlzIG9wdGlvbiBpcyBvbmx5IGhv
+bm9yZWQgd2hlbgpnaXZlbiBvbiB0aGUgY29tbWFuZCBsaW5lLgoKQGl0ZW0gLS1m
+YWtlZC1zeXN0ZW0tdGltZSBAdmFye2Vwb2NofQpAb3BpbmRleCBmYWtlZC1zeXN0
+ZW0tdGltZQpUaGlzIG9wdGlvbiBpcyBvbmx5IHVzZWZ1bCBmb3IgdGVzdGluZzsg
+aXQgc2V0cyB0aGUgc3lzdGVtIHRpbWUgYmFjayBvcgpmb3J0aCB0byBAdmFye2Vw
+b2NofSB3aGljaCBpcyB0aGUgbnVtYmVyIG9mIHNlY29uZHMgZWxhcHNlZCBzaW5j
+ZSB0aGUgeWVhcgoxOTcwLiAgQWx0ZXJuYXRpdmVseSBAdmFye2Vwb2NofSBtYXkg
+YmUgZ2l2ZW4gYXMgYSBmdWxsIElTTyB0aW1lIHN0cmluZwooZS5nLiAiMjAwNzA5
+MjRUMTU0ODEyIikuCgpAaXRlbSAtLWVuYWJsZS1wcm9ncmVzcy1maWx0ZXIKQG9w
+aW5kZXggZW5hYmxlLXByb2dyZXNzLWZpbHRlcgpFbmFibGUgY2VydGFpbiBQUk9H
+UkVTUyBzdGF0dXMgb3V0cHV0cy4gVGhpcyBvcHRpb24gYWxsb3dzIGZyb250ZW5k
+cwp0byBkaXNwbGF5IGEgcHJvZ3Jlc3MgaW5kaWNhdG9yIHdoaWxlIGdwZyBpcyBw
+cm9jZXNzaW5nIGxhcmdlciBmaWxlcy4KVGhlcmUgaXMgYSBzbGlnaHQgcGVyZm9y
+bWFuY2Ugb3ZlcmhlYWQgdXNpbmcgaXQuCgpAaXRlbSAtLXN0YXR1cy1mZCBAY29k
+ZXtufQpAb3BpbmRleCBzdGF0dXMtZmQKV3JpdGUgc3BlY2lhbCBzdGF0dXMgc3Ry
+aW5ncyB0byB0aGUgZmlsZSBkZXNjcmlwdG9yIEBjb2Rle259LgpTZWUgdGhlIGZp
+bGUgREVUQUlMUyBpbiB0aGUgZG9jdW1lbnRhdGlvbiBmb3IgYSBsaXN0aW5nIG9m
+IHRoZW0uCgpAaXRlbSAtLXN0YXR1cy1maWxlIEBjb2Rle2ZpbGV9CkBvcGluZGV4
+IHN0YXR1cy1maWxlClNhbWUgYXMgQG9wdGlvbnstLXN0YXR1cy1mZH0sIGV4Y2Vw
+dCB0aGUgc3RhdHVzIGRhdGEgaXMgd3JpdHRlbiB0byBmaWxlCkBjb2Rle2ZpbGV9
+LgoKQGl0ZW0gLS1sb2dnZXItZmQgQGNvZGV7bn0KQG9waW5kZXggbG9nZ2VyLWZk
+CldyaXRlIGxvZyBvdXRwdXQgdG8gZmlsZSBkZXNjcmlwdG9yIEBjb2Rle259IGFu
+ZCBub3QgdG8gU1RERVJSLgoKQGl0ZW0gLS1sb2ctZmlsZSBAY29kZXtmaWxlfQpA
+aXRlbXggLS1sb2dnZXItZmlsZSBAY29kZXtmaWxlfQpAb3BpbmRleCBsb2ctZmls
+ZQpTYW1lIGFzIEBvcHRpb257LS1sb2dnZXItZmR9LCBleGNlcHQgdGhlIGxvZ2dl
+ciBkYXRhIGlzIHdyaXR0ZW4gdG8gZmlsZQpAY29kZXtmaWxlfS4gIE5vdGUgdGhh
+dCBAb3B0aW9uey0tbG9nLWZpbGV9IGlzIG9ubHkgaW1wbGVtZW50ZWQgZm9yCkdu
+dVBHLTIuCgpAaXRlbSAtLWF0dHJpYnV0ZS1mZCBAY29kZXtufQpAb3BpbmRleCBh
+dHRyaWJ1dGUtZmQKV3JpdGUgYXR0cmlidXRlIHN1YnBhY2tldHMgdG8gdGhlIGZp
+bGUgZGVzY3JpcHRvciBAY29kZXtufS4gVGhpcyBpcyBtb3N0CnVzZWZ1bCBmb3Ig
+dXNlIHdpdGggQG9wdGlvbnstLXN0YXR1cy1mZH0sIHNpbmNlIHRoZSBzdGF0dXMg
+bWVzc2FnZXMgYXJlCm5lZWRlZCB0byBzZXBhcmF0ZSBvdXQgdGhlIHZhcmlvdXMg
+c3VicGFja2V0cyBmcm9tIHRoZSBzdHJlYW0gZGVsaXZlcmVkCnRvIHRoZSBmaWxl
+IGRlc2NyaXB0b3IuCgpAaXRlbSAtLWF0dHJpYnV0ZS1maWxlIEBjb2Rle2ZpbGV9
+CkBvcGluZGV4IGF0dHJpYnV0ZS1maWxlClNhbWUgYXMgQG9wdGlvbnstLWF0dHJp
+YnV0ZS1mZH0sIGV4Y2VwdCB0aGUgYXR0cmlidXRlIGRhdGEgaXMgd3JpdHRlbiB0
+bwpmaWxlIEBjb2Rle2ZpbGV9LgoKQGl0ZW0gLS1jb21tZW50IEBjb2Rle3N0cmlu
+Z30KQGl0ZW14IC0tbm8tY29tbWVudHMKQG9waW5kZXggY29tbWVudApVc2UgQGNv
+ZGV7c3RyaW5nfSBhcyBhIGNvbW1lbnQgc3RyaW5nIGluIGNsZWFyIHRleHQgc2ln
+bmF0dXJlcyBhbmQgQVNDSUkKYXJtb3JlZCBtZXNzYWdlcyBvciBrZXlzIChzZWUg
+QG9wdGlvbnstLWFybW9yfSkuIFRoZSBkZWZhdWx0IGJlaGF2aW9yIGlzCm5vdCB0
+byB1c2UgYSBjb21tZW50IHN0cmluZy4gQG9wdGlvbnstLWNvbW1lbnR9IG1heSBi
+ZSByZXBlYXRlZCBtdWx0aXBsZQp0aW1lcyB0byBnZXQgbXVsdGlwbGUgY29tbWVu
+dCBzdHJpbmdzLiBAb3B0aW9uey0tbm8tY29tbWVudHN9IHJlbW92ZXMKYWxsIGNv
+bW1lbnRzLiAgSXQgaXMgYSBnb29kIGlkZWEgdG8ga2VlcCB0aGUgbGVuZ3RoIG9m
+IGEgc2luZ2xlIGNvbW1lbnQKYmVsb3cgNjAgY2hhcmFjdGVycyB0byBhdm9pZCBw
+cm9ibGVtcyB3aXRoIG1haWwgcHJvZ3JhbXMgd3JhcHBpbmcgc3VjaApsaW5lcy4g
+IE5vdGUgdGhhdCBjb21tZW50IGxpbmVzLCBsaWtlIGFsbCBvdGhlciBoZWFkZXIg
+bGluZXMsIGFyZSBub3QKcHJvdGVjdGVkIGJ5IHRoZSBzaWduYXR1cmUuCgpAaXRl
+bSAtLWVtaXQtdmVyc2lvbgpAaXRlbXggLS1uby1lbWl0LXZlcnNpb24KQG9waW5k
+ZXggZW1pdC12ZXJzaW9uCkZvcmNlIGluY2x1c2lvbiBvZiB0aGUgdmVyc2lvbiBz
+dHJpbmcgaW4gQVNDSUkgYXJtb3JlZCBvdXRwdXQuICBJZgpnaXZlbiBvbmNlIG9u
+bHkgdGhlIG5hbWUgb2YgdGhlIHByb2dyYW0gYW5kIHRoZSBtYWpvciBudW1iZXIg
+aXMKZW1pdHRlZCAoZGVmYXVsdCksIGdpdmVuIHR3aWNlIHRoZSBtaW5vciBpcyBh
+bHNvIGVtaXR0ZWQsIGdpdmVuIHRyaXBsZQp0aGUgbWljcm8gaXMgYWRkZWQsIGFu
+ZCBnaXZlbiBxdWFkIGFuIG9wZXJhdGluZyBzeXN0ZW0gaWRlbnRpZmljYXRpb24K
+aXMgYWxzbyBlbWl0dGVkLiAgQG9wdGlvbnstLW5vLWVtaXQtdmVyc2lvbn0gZGlz
+YWJsZXMgdGhlIHZlcnNpb24KbGluZS4KCkBpdGVtIC0tc2lnLW5vdGF0aW9uIEBj
+b2Rle25hbWU9dmFsdWV9CkBpdGVteCAtLWNlcnQtbm90YXRpb24gQGNvZGV7bmFt
+ZT12YWx1ZX0KQGl0ZW14IC1OLCAtLXNldC1ub3RhdGlvbiBAY29kZXtuYW1lPXZh
+bHVlfQpAb3BpbmRleCBzaWctbm90YXRpb24KQG9waW5kZXggY2VydC1ub3RhdGlv
+bgpAb3BpbmRleCBzZXQtbm90YXRpb24KUHV0IHRoZSBuYW1lIHZhbHVlIHBhaXIg
+aW50byB0aGUgc2lnbmF0dXJlIGFzIG5vdGF0aW9uIGRhdGEuCkBjb2Rle25hbWV9
+IG11c3QgY29uc2lzdCBvbmx5IG9mIHByaW50YWJsZSBjaGFyYWN0ZXJzIG9yIHNw
+YWNlcywgYW5kCm11c3QgY29udGFpbiBhICdAQCcgY2hhcmFjdGVyIGluIHRoZSBm
+b3JtIGtleW5hbWVAQGRvbWFpbi5leGFtcGxlLmNvbQooc3Vic3RpdHV0aW5nIHRo
+ZSBhcHByb3ByaWF0ZSBrZXluYW1lIGFuZCBkb21haW4gbmFtZSwgb2YgY291cnNl
+KS4gIFRoaXMKaXMgdG8gaGVscCBwcmV2ZW50IHBvbGx1dGlvbiBvZiB0aGUgSUVU
+RiByZXNlcnZlZCBub3RhdGlvbgpuYW1lc3BhY2UuIFRoZSBAb3B0aW9uey0tZXhw
+ZXJ0fSBmbGFnIG92ZXJyaWRlcyB0aGUgJ0BAJwpjaGVjay4gQGNvZGV7dmFsdWV9
+IG1heSBiZSBhbnkgcHJpbnRhYmxlIHN0cmluZzsgaXQgd2lsbCBiZSBlbmNvZGVk
+IGluClVURjgsIHNvIHlvdSBzaG91bGQgY2hlY2sgdGhhdCB5b3VyIEBvcHRpb257
+LS1kaXNwbGF5LWNoYXJzZXR9IGlzIHNldApjb3JyZWN0bHkuIElmIHlvdSBwcmVm
+aXggQGNvZGV7bmFtZX0gd2l0aCBhbiBleGNsYW1hdGlvbiBtYXJrICghKSwgdGhl
+Cm5vdGF0aW9uIGRhdGEgd2lsbCBiZSBmbGFnZ2VkIGFzIGNyaXRpY2FsCihyZmM0
+ODgwOjUuMi4zLjE2KS4gQG9wdGlvbnstLXNpZy1ub3RhdGlvbn0gc2V0cyBhIG5v
+dGF0aW9uIGZvciBkYXRhCnNpZ25hdHVyZXMuIEBvcHRpb257LS1jZXJ0LW5vdGF0
+aW9ufSBzZXRzIGEgbm90YXRpb24gZm9yIGtleSBzaWduYXR1cmVzCihjZXJ0aWZp
+Y2F0aW9ucykuIEBvcHRpb257LS1zZXQtbm90YXRpb259IHNldHMgYm90aC4KClRo
+ZXJlIGFyZSBzcGVjaWFsIGNvZGVzIHRoYXQgbWF5IGJlIHVzZWQgaW4gbm90YXRp
+b24gbmFtZXMuICIlayIgd2lsbApiZSBleHBhbmRlZCBpbnRvIHRoZSBrZXkgSUQg
+b2YgdGhlIGtleSBiZWluZyBzaWduZWQsICIlSyIgaW50byB0aGUKbG9uZyBrZXkg
+SUQgb2YgdGhlIGtleSBiZWluZyBzaWduZWQsICIlZiIgaW50byB0aGUgZmluZ2Vy
+cHJpbnQgb2YgdGhlCmtleSBiZWluZyBzaWduZWQsICIlcyIgaW50byB0aGUga2V5
+IElEIG9mIHRoZSBrZXkgbWFraW5nIHRoZQpzaWduYXR1cmUsICIlUyIgaW50byB0
+aGUgbG9uZyBrZXkgSUQgb2YgdGhlIGtleSBtYWtpbmcgdGhlIHNpZ25hdHVyZSwK
+IiVnIiBpbnRvIHRoZSBmaW5nZXJwcmludCBvZiB0aGUga2V5IG1ha2luZyB0aGUg
+c2lnbmF0dXJlICh3aGljaCBtaWdodApiZSBhIHN1YmtleSksICIlcCIgaW50byB0
+aGUgZmluZ2VycHJpbnQgb2YgdGhlIHByaW1hcnkga2V5IG9mIHRoZSBrZXkKbWFr
+aW5nIHRoZSBzaWduYXR1cmUsICIlYyIgaW50byB0aGUgc2lnbmF0dXJlIGNvdW50
+IGZyb20gdGhlIE9wZW5QR1AKc21hcnRjYXJkLCBhbmQgIiUlIiByZXN1bHRzIGlu
+IGEgc2luZ2xlICIlIi4gJWssICVLLCBhbmQgJWYgYXJlIG9ubHkKbWVhbmluZ2Z1
+bCB3aGVuIG1ha2luZyBhIGtleSBzaWduYXR1cmUgKGNlcnRpZmljYXRpb24pLCBh
+bmQgJWMgaXMgb25seQptZWFuaW5nZnVsIHdoZW4gdXNpbmcgdGhlIE9wZW5QR1Ag
+c21hcnRjYXJkLgoKQGl0ZW0gLS1zaWctcG9saWN5LXVybCBAY29kZXtzdHJpbmd9
+CkBpdGVteCAtLWNlcnQtcG9saWN5LXVybCBAY29kZXtzdHJpbmd9CkBpdGVteCAt
+LXNldC1wb2xpY3ktdXJsIEBjb2Rle3N0cmluZ30KQG9waW5kZXggc2lnLXBvbGlj
+eS11cmwKQG9waW5kZXggY2VydC1wb2xpY3ktdXJsCkBvcGluZGV4IHNldC1wb2xp
+Y3ktdXJsClVzZSBAY29kZXtzdHJpbmd9IGFzIGEgUG9saWN5IFVSTCBmb3Igc2ln
+bmF0dXJlcyAocmZjNDg4MDo1LjIuMy4yMCkuICBJZgp5b3UgcHJlZml4IGl0IHdp
+dGggYW4gZXhjbGFtYXRpb24gbWFyayAoISksIHRoZSBwb2xpY3kgVVJMIHBhY2tl
+dCB3aWxsCmJlIGZsYWdnZWQgYXMgY3JpdGljYWwuIEBvcHRpb257LS1zaWctcG9s
+aWN5LXVybH0gc2V0cyBhIHBvbGljeSB1cmwgZm9yCmRhdGEgc2lnbmF0dXJlcy4g
+QG9wdGlvbnstLWNlcnQtcG9saWN5LXVybH0gc2V0cyBhIHBvbGljeSB1cmwgZm9y
+IGtleQpzaWduYXR1cmVzIChjZXJ0aWZpY2F0aW9ucykuIEBvcHRpb257LS1zZXQt
+cG9saWN5LXVybH0gc2V0cyBib3RoLgoKVGhlIHNhbWUgJS1leHBhbmRvcyB1c2Vk
+IGZvciBub3RhdGlvbiBkYXRhIGFyZSBhdmFpbGFibGUgaGVyZSBhcyB3ZWxsLgoK
+QGl0ZW0gLS1zaWcta2V5c2VydmVyLXVybCBAY29kZXtzdHJpbmd9CkBvcGluZGV4
+IHNpZy1rZXlzZXJ2ZXItdXJsClVzZSBAY29kZXtzdHJpbmd9IGFzIGEgcHJlZmVy
+cmVkIGtleXNlcnZlciBVUkwgZm9yIGRhdGEgc2lnbmF0dXJlcy4gSWYKeW91IHBy
+ZWZpeCBpdCB3aXRoIGFuIGV4Y2xhbWF0aW9uIG1hcmsgKCEpLCB0aGUga2V5c2Vy
+dmVyIFVSTCBwYWNrZXQKd2lsbCBiZSBmbGFnZ2VkIGFzIGNyaXRpY2FsLgoKVGhl
+IHNhbWUgJS1leHBhbmRvcyB1c2VkIGZvciBub3RhdGlvbiBkYXRhIGFyZSBhdmFp
+bGFibGUgaGVyZSBhcyB3ZWxsLgoKQGl0ZW0gLS1zZXQtZmlsZW5hbWUgQGNvZGV7
+c3RyaW5nfQpAb3BpbmRleCBzZXQtZmlsZW5hbWUKVXNlIEBjb2Rle3N0cmluZ30g
+YXMgdGhlIGZpbGVuYW1lIHdoaWNoIGlzIHN0b3JlZCBpbnNpZGUgbWVzc2FnZXMu
+ClRoaXMgb3ZlcnJpZGVzIHRoZSBkZWZhdWx0LCB3aGljaCBpcyB0byB1c2UgdGhl
+IGFjdHVhbCBmaWxlbmFtZSBvZiB0aGUKZmlsZSBiZWluZyBlbmNyeXB0ZWQuICBV
+c2luZyB0aGUgZW1wdHkgc3RyaW5nIGZvciBAdmFye3N0cmluZ30KZWZmZWN0aXZl
+bHkgcmVtb3ZlcyB0aGUgZmlsZW5hbWUgZnJvbSB0aGUgb3V0cHV0LgoKQGl0ZW0g
+LS1mb3IteW91ci1leWVzLW9ubHkKQGl0ZW14IC0tbm8tZm9yLXlvdXItZXllcy1v
+bmx5CkBvcGluZGV4IGZvci15b3VyLWV5ZXMtb25seQpTZXQgdGhlIGBmb3IgeW91
+ciBleWVzIG9ubHknIGZsYWcgaW4gdGhlIG1lc3NhZ2UuIFRoaXMgY2F1c2VzIEdu
+dVBHIHRvCnJlZnVzZSB0byBzYXZlIHRoZSBmaWxlIHVubGVzcyB0aGUgQG9wdGlv
+bnstLW91dHB1dH0gb3B0aW9uIGlzIGdpdmVuLAphbmQgUEdQIHRvIHVzZSBhICJz
+ZWN1cmUgdmlld2VyIiB3aXRoIGEgY2xhaW1lZCBUZW1wZXN0LXJlc2lzdGFudCBm
+b250CnRvIGRpc3BsYXkgdGhlIG1lc3NhZ2UuIFRoaXMgb3B0aW9uIG92ZXJyaWRl
+cyBAb3B0aW9uey0tc2V0LWZpbGVuYW1lfS4KQG9wdGlvbnstLW5vLWZvci15b3Vy
+LWV5ZXMtb25seX0gZGlzYWJsZXMgdGhpcyBvcHRpb24uCgpAaXRlbSAtLXVzZS1l
+bWJlZGRlZC1maWxlbmFtZQpAaXRlbXggLS1uby11c2UtZW1iZWRkZWQtZmlsZW5h
+bWUKQG9waW5kZXggdXNlLWVtYmVkZGVkLWZpbGVuYW1lClRyeSB0byBjcmVhdGUg
+YSBmaWxlIHdpdGggYSBuYW1lIGFzIGVtYmVkZGVkIGluIHRoZSBkYXRhLiBUaGlz
+IGNhbiBiZQphIGRhbmdlcm91cyBvcHRpb24gYXMgaXQgYWxsb3dzIHRvIG92ZXJ3
+cml0ZSBmaWxlcy4gRGVmYXVsdHMgdG8gbm8uCgpAaXRlbSAtLWNpcGhlci1hbGdv
+IEBjb2Rle25hbWV9CkBvcGluZGV4IGNpcGhlci1hbGdvClVzZSBAY29kZXtuYW1l
+fSBhcyBjaXBoZXIgYWxnb3JpdGhtLiBSdW5uaW5nIHRoZSBwcm9ncmFtIHdpdGgg
+dGhlCmNvbW1hbmQgQG9wdGlvbnstLXZlcnNpb259IHlpZWxkcyBhIGxpc3Qgb2Yg
+c3VwcG9ydGVkIGFsZ29yaXRobXMuIElmCnRoaXMgaXMgbm90IHVzZWQgdGhlIGNp
+cGhlciBhbGdvcml0aG0gaXMgc2VsZWN0ZWQgZnJvbSB0aGUgcHJlZmVyZW5jZXMK
+c3RvcmVkIHdpdGggdGhlIGtleS4gSW4gZ2VuZXJhbCwgeW91IGRvIG5vdCB3YW50
+IHRvIHVzZSB0aGlzIG9wdGlvbiBhcwppdCBhbGxvd3MgeW91IHRvIHZpb2xhdGUg
+dGhlIE9wZW5QR1Agc3RhbmRhcmQuCkBvcHRpb257LS1wZXJzb25hbC1jaXBoZXIt
+cHJlZmVyZW5jZXN9IGlzIHRoZSBzYWZlIHdheSB0byBhY2NvbXBsaXNoIHRoZQpz
+YW1lIHRoaW5nLgoKQGl0ZW0gLS1kaWdlc3QtYWxnbyBAY29kZXtuYW1lfQpAb3Bp
+bmRleCBkaWdlc3QtYWxnbwpVc2UgQGNvZGV7bmFtZX0gYXMgdGhlIG1lc3NhZ2Ug
+ZGlnZXN0IGFsZ29yaXRobS4gUnVubmluZyB0aGUgcHJvZ3JhbQp3aXRoIHRoZSBj
+b21tYW5kIEBvcHRpb257LS12ZXJzaW9ufSB5aWVsZHMgYSBsaXN0IG9mIHN1cHBv
+cnRlZCBhbGdvcml0aG1zLiBJbgpnZW5lcmFsLCB5b3UgZG8gbm90IHdhbnQgdG8g
+dXNlIHRoaXMgb3B0aW9uIGFzIGl0IGFsbG93cyB5b3UgdG8KdmlvbGF0ZSB0aGUg
+T3BlblBHUCBzdGFuZGFyZC4gQG9wdGlvbnstLXBlcnNvbmFsLWRpZ2VzdC1wcmVm
+ZXJlbmNlc30gaXMgdGhlCnNhZmUgd2F5IHRvIGFjY29tcGxpc2ggdGhlIHNhbWUg
+dGhpbmcuCgpAaXRlbSAtLWNvbXByZXNzLWFsZ28gQGNvZGV7bmFtZX0KQG9waW5k
+ZXggY29tcHJlc3MtYWxnbwpVc2UgY29tcHJlc3Npb24gYWxnb3JpdGhtIEBjb2Rl
+e25hbWV9LiAiemxpYiIgaXMgUkZDLTE5NTAgWkxJQgpjb21wcmVzc2lvbi4gInpp
+cCIgaXMgUkZDLTE5NTEgWklQIGNvbXByZXNzaW9uIHdoaWNoIGlzIHVzZWQgYnkg
+UEdQLgoiYnppcDIiIGlzIGEgbW9yZSBtb2Rlcm4gY29tcHJlc3Npb24gc2NoZW1l
+IHRoYXQgY2FuIGNvbXByZXNzIHNvbWUKdGhpbmdzIGJldHRlciB0aGFuIHppcCBv
+ciB6bGliLCBidXQgYXQgdGhlIGNvc3Qgb2YgbW9yZSBtZW1vcnkgdXNlZApkdXJp
+bmcgY29tcHJlc3Npb24gYW5kIGRlY29tcHJlc3Npb24uICJ1bmNvbXByZXNzZWQi
+IG9yICJub25lIgpkaXNhYmxlcyBjb21wcmVzc2lvbi4gSWYgdGhpcyBvcHRpb24g
+aXMgbm90IHVzZWQsIHRoZSBkZWZhdWx0CmJlaGF2aW9yIGlzIHRvIGV4YW1pbmUg
+dGhlIHJlY2lwaWVudCBrZXkgcHJlZmVyZW5jZXMgdG8gc2VlIHdoaWNoCmFsZ29y
+aXRobXMgdGhlIHJlY2lwaWVudCBzdXBwb3J0cy4gSWYgYWxsIGVsc2UgZmFpbHMs
+IFpJUCBpcyB1c2VkIGZvcgptYXhpbXVtIGNvbXBhdGliaWxpdHkuCgpaTElCIG1h
+eSBnaXZlIGJldHRlciBjb21wcmVzc2lvbiByZXN1bHRzIHRoYW4gWklQLCBhcyB0
+aGUgY29tcHJlc3Npb24Kd2luZG93IHNpemUgaXMgbm90IGxpbWl0ZWQgdG8gOGsu
+IEJaSVAyIG1heSBnaXZlIGV2ZW4gYmV0dGVyCmNvbXByZXNzaW9uIHJlc3VsdHMg
+dGhhbiB0aGF0LCBidXQgd2lsbCB1c2UgYSBzaWduaWZpY2FudGx5IGxhcmdlcgph
+bW91bnQgb2YgbWVtb3J5IHdoaWxlIGNvbXByZXNzaW5nIGFuZCBkZWNvbXByZXNz
+aW5nLiBUaGlzIG1heSBiZQpzaWduaWZpY2FudCBpbiBsb3cgbWVtb3J5IHNpdHVh
+dGlvbnMuIE5vdGUsIGhvd2V2ZXIsIHRoYXQgUEdQIChhbGwKdmVyc2lvbnMpIG9u
+bHkgc3VwcG9ydHMgWklQIGNvbXByZXNzaW9uLiBVc2luZyBhbnkgYWxnb3JpdGht
+IG90aGVyCnRoYW4gWklQIG9yICJub25lIiB3aWxsIG1ha2UgdGhlIG1lc3NhZ2Ug
+dW5yZWFkYWJsZSB3aXRoIFBHUC4gSW4KZ2VuZXJhbCwgeW91IGRvIG5vdCB3YW50
+IHRvIHVzZSB0aGlzIG9wdGlvbiBhcyBpdCBhbGxvd3MgeW91IHRvCnZpb2xhdGUg
+dGhlIE9wZW5QR1Agc3RhbmRhcmQuIEBvcHRpb257LS1wZXJzb25hbC1jb21wcmVz
+cy1wcmVmZXJlbmNlc30gaXMgdGhlCnNhZmUgd2F5IHRvIGFjY29tcGxpc2ggdGhl
+IHNhbWUgdGhpbmcuCgpAaXRlbSAtLWNlcnQtZGlnZXN0LWFsZ28gQGNvZGV7bmFt
+ZX0KQG9waW5kZXggY2VydC1kaWdlc3QtYWxnbwpVc2UgQGNvZGV7bmFtZX0gYXMg
+dGhlIG1lc3NhZ2UgZGlnZXN0IGFsZ29yaXRobSB1c2VkIHdoZW4gc2lnbmluZyBh
+CmtleS4gUnVubmluZyB0aGUgcHJvZ3JhbSB3aXRoIHRoZSBjb21tYW5kIEBvcHRp
+b257LS12ZXJzaW9ufSB5aWVsZHMgYQpsaXN0IG9mIHN1cHBvcnRlZCBhbGdvcml0
+aG1zLiBCZSBhd2FyZSB0aGF0IGlmIHlvdSBjaG9vc2UgYW4gYWxnb3JpdGhtCnRo
+YXQgR251UEcgc3VwcG9ydHMgYnV0IG90aGVyIE9wZW5QR1AgaW1wbGVtZW50YXRp
+b25zIGRvIG5vdCwgdGhlbiBzb21lCnVzZXJzIHdpbGwgbm90IGJlIGFibGUgdG8g
+dXNlIHRoZSBrZXkgc2lnbmF0dXJlcyB5b3UgbWFrZSwgb3IgcXVpdGUKcG9zc2li
+bHkgeW91ciBlbnRpcmUga2V5LgoKQGl0ZW0gLS1kaXNhYmxlLWNpcGhlci1hbGdv
+IEBjb2Rle25hbWV9CkBvcGluZGV4IGRpc2FibGUtY2lwaGVyLWFsZ28KTmV2ZXIg
+YWxsb3cgdGhlIHVzZSBvZiBAY29kZXtuYW1lfSBhcyBjaXBoZXIgYWxnb3JpdGht
+LgpUaGUgZ2l2ZW4gbmFtZSB3aWxsIG5vdCBiZSBjaGVja2VkIHNvIHRoYXQgYSBs
+YXRlciBsb2FkZWQgYWxnb3JpdGhtCndpbGwgc3RpbGwgZ2V0IGRpc2FibGVkLgoK
+QGl0ZW0gLS1kaXNhYmxlLXB1YmtleS1hbGdvIEBjb2Rle25hbWV9CkBvcGluZGV4
+IGRpc2FibGUtcHVia2V5LWFsZ28KTmV2ZXIgYWxsb3cgdGhlIHVzZSBvZiBAY29k
+ZXtuYW1lfSBhcyBwdWJsaWMga2V5IGFsZ29yaXRobS4KVGhlIGdpdmVuIG5hbWUg
+d2lsbCBub3QgYmUgY2hlY2tlZCBzbyB0aGF0IGEgbGF0ZXIgbG9hZGVkIGFsZ29y
+aXRobQp3aWxsIHN0aWxsIGdldCBkaXNhYmxlZC4KCkBpdGVtIC0tdGhyb3cta2V5
+aWRzCkBpdGVteCAtLW5vLXRocm93LWtleWlkcwpAb3BpbmRleCB0aHJvdy1rZXlp
+ZHMKRG8gbm90IHB1dCB0aGUgcmVjaXBpZW50IGtleSBJRHMgaW50byBlbmNyeXB0
+ZWQgbWVzc2FnZXMuIFRoaXMgaGVscHMgdG8KaGlkZSB0aGUgcmVjZWl2ZXJzIG9m
+IHRoZSBtZXNzYWdlIGFuZCBpcyBhIGxpbWl0ZWQgY291bnRlcm1lYXN1cmUKYWdh
+aW5zdCB0cmFmZmljIGFuYWx5c2lzLkBmb290bm90ZXtVc2luZyBhIGxpdHRsZSBz
+b2NpYWwgZW5naW5lZXJpbmcKYW55b25lIHdobyBpcyBhYmxlIHRvIGRlY3J5cHQg
+dGhlIG1lc3NhZ2UgY2FuIGNoZWNrIHdoZXRoZXIgb25lIG9mIHRoZQpvdGhlciBy
+ZWNpcGllbnRzIGlzIHRoZSBvbmUgaGUgc3VzcGVjdHMufSAgT24gdGhlIHJlY2Vp
+dmluZyBzaWRlLCBpdCBtYXkKc2xvdyBkb3duIHRoZSBkZWNyeXB0aW9uIHByb2Nl
+c3MgYmVjYXVzZSBhbGwgYXZhaWxhYmxlIHNlY3JldCBrZXlzIG11c3QKYmUgdHJp
+ZWQuICBAb3B0aW9uey0tbm8tdGhyb3cta2V5aWRzfSBkaXNhYmxlcyB0aGlzIG9w
+dGlvbi4gVGhpcyBvcHRpb24KaXMgZXNzZW50aWFsbHkgdGhlIHNhbWUgYXMgdXNp
+bmcgQG9wdGlvbnstLWhpZGRlbi1yZWNpcGllbnR9IGZvciBhbGwKcmVjaXBpZW50
+cy4KCkBpdGVtIC0tbm90LWRhc2gtZXNjYXBlZApAb3BpbmRleCBub3QtZGFzaC1l
+c2NhcGVkClRoaXMgb3B0aW9uIGNoYW5nZXMgdGhlIGJlaGF2aW9yIG9mIGNsZWFy
+dGV4dCBzaWduYXR1cmVzCnNvIHRoYXQgdGhleSBjYW4gYmUgdXNlZCBmb3IgcGF0
+Y2ggZmlsZXMuIFlvdSBzaG91bGQgbm90CnNlbmQgc3VjaCBhbiBhcm1vcmVkIGZp
+bGUgdmlhIGVtYWlsIGJlY2F1c2UgYWxsIHNwYWNlcwphbmQgbGluZSBlbmRpbmdz
+IGFyZSBoYXNoZWQgdG9vLiBZb3UgY2FuIG5vdCB1c2UgdGhpcwpvcHRpb24gZm9y
+IGRhdGEgd2hpY2ggaGFzIDUgZGFzaGVzIGF0IHRoZSBiZWdpbm5pbmcgb2YgYQps
+aW5lLCBwYXRjaCBmaWxlcyBkb24ndCBoYXZlIHRoaXMuIEEgc3BlY2lhbCBhcm1v
+ciBoZWFkZXIKbGluZSB0ZWxscyBHbnVQRyBhYm91dCB0aGlzIGNsZWFydGV4dCBz
+aWduYXR1cmUgb3B0aW9uLgoKQGl0ZW0gLS1lc2NhcGUtZnJvbS1saW5lcwpAaXRl
+bXggLS1uby1lc2NhcGUtZnJvbS1saW5lcwpAb3BpbmRleCBlc2NhcGUtZnJvbS1s
+aW5lcwpCZWNhdXNlIHNvbWUgbWFpbGVycyBjaGFuZ2UgbGluZXMgc3RhcnRpbmcg
+d2l0aCAiRnJvbSAiIHRvICI+RnJvbSAiIGl0CmlzIGdvb2QgdG8gaGFuZGxlIHN1
+Y2ggbGluZXMgaW4gYSBzcGVjaWFsIHdheSB3aGVuIGNyZWF0aW5nIGNsZWFydGV4
+dApzaWduYXR1cmVzIHRvIHByZXZlbnQgdGhlIG1haWwgc3lzdGVtIGZyb20gYnJl
+YWtpbmcgdGhlIHNpZ25hdHVyZS4gTm90ZQp0aGF0IGFsbCBvdGhlciBQR1AgdmVy
+c2lvbnMgZG8gaXQgdGhpcyB3YXkgdG9vLiAgRW5hYmxlZCBieQpkZWZhdWx0LiBA
+b3B0aW9uey0tbm8tZXNjYXBlLWZyb20tbGluZXN9IGRpc2FibGVzIHRoaXMgb3B0
+aW9uLgoKQGl0ZW0gLS1wYXNzcGhyYXNlLXJlcGVhdCBAY29kZXtufQpAb3BpbmRl
+eCBwYXNzcGhyYXNlLXJlcGVhdApTcGVjaWZ5IGhvdyBtYW55IHRpbWVzIEBjb21t
+YW5ke0BncGduYW1lfSB3aWxsIHJlcXVlc3QgYSBuZXcKcGFzc3BocmFzZSBiZSBy
+ZXBlYXRlZC4gIFRoaXMgaXMgdXNlZnVsIGZvciBoZWxwaW5nIG1lbW9yaXplIGEK
+cGFzc3BocmFzZS4gIERlZmF1bHRzIHRvIDEgcmVwZXRpdGlvbi4KCkBpdGVtIC0t
+cGFzc3BocmFzZS1mZCBAY29kZXtufQpAb3BpbmRleCBwYXNzcGhyYXNlLWZkClJl
+YWQgdGhlIHBhc3NwaHJhc2UgZnJvbSBmaWxlIGRlc2NyaXB0b3IgQGNvZGV7bn0u
+IE9ubHkgdGhlIGZpcnN0IGxpbmUKd2lsbCBiZSByZWFkIGZyb20gZmlsZSBkZXNj
+cmlwdG9yIEBjb2Rle259LiBJZiB5b3UgdXNlIDAgZm9yIEBjb2Rle259LAp0aGUg
+cGFzc3BocmFzZSB3aWxsIGJlIHJlYWQgZnJvbSBTVERJTi4gVGhpcyBjYW4gb25s
+eSBiZSB1c2VkIGlmIG9ubHkKb25lIHBhc3NwaHJhc2UgaXMgc3VwcGxpZWQuCgpO
+b3RlIHRoYXQgdGhpcyBwYXNzcGhyYXNlIGlzIG9ubHkgdXNlZCBpZiB0aGUgb3B0
+aW9uIEBvcHRpb257LS1iYXRjaH0KaGFzIGFsc28gYmVlbiBnaXZlbi4gIFRoaXMg
+aXMgZGlmZmVyZW50IGZyb20gR251UEcgdmVyc2lvbiAxLnguCgpAaXRlbSAtLXBh
+c3NwaHJhc2UtZmlsZSBAY29kZXtmaWxlfQpAb3BpbmRleCBwYXNzcGhyYXNlLWZp
+bGUKUmVhZCB0aGUgcGFzc3BocmFzZSBmcm9tIGZpbGUgQGNvZGV7ZmlsZX0uIE9u
+bHkgdGhlIGZpcnN0IGxpbmUgd2lsbApiZSByZWFkIGZyb20gZmlsZSBAY29kZXtm
+aWxlfS4gVGhpcyBjYW4gb25seSBiZSB1c2VkIGlmIG9ubHkgb25lCnBhc3NwaHJh
+c2UgaXMgc3VwcGxpZWQuIE9idmlvdXNseSwgYSBwYXNzcGhyYXNlIHN0b3JlZCBp
+biBhIGZpbGUgaXMKb2YgcXVlc3Rpb25hYmxlIHNlY3VyaXR5IGlmIG90aGVyIHVz
+ZXJzIGNhbiByZWFkIHRoaXMgZmlsZS4gRG9uJ3QgdXNlCnRoaXMgb3B0aW9uIGlm
+IHlvdSBjYW4gYXZvaWQgaXQuCk5vdGUgdGhhdCB0aGlzIHBhc3NwaHJhc2UgaXMg
+b25seSB1c2VkIGlmIHRoZSBvcHRpb24gQG9wdGlvbnstLWJhdGNofQpoYXMgYWxz
+byBiZWVuIGdpdmVuLiAgVGhpcyBpcyBkaWZmZXJlbnQgZnJvbSBHbnVQRyB2ZXJz
+aW9uIDEueC4KCkBpdGVtIC0tcGFzc3BocmFzZSBAY29kZXtzdHJpbmd9CkBvcGlu
+ZGV4IHBhc3NwaHJhc2UKVXNlIEBjb2Rle3N0cmluZ30gYXMgdGhlIHBhc3NwaHJh
+c2UuIFRoaXMgY2FuIG9ubHkgYmUgdXNlZCBpZiBvbmx5IG9uZQpwYXNzcGhyYXNl
+IGlzIHN1cHBsaWVkLiBPYnZpb3VzbHksIHRoaXMgaXMgb2YgdmVyeSBxdWVzdGlv
+bmFibGUKc2VjdXJpdHkgb24gYSBtdWx0aS11c2VyIHN5c3RlbS4gRG9uJ3QgdXNl
+IHRoaXMgb3B0aW9uIGlmIHlvdSBjYW4KYXZvaWQgaXQuCk5vdGUgdGhhdCB0aGlz
+IHBhc3NwaHJhc2UgaXMgb25seSB1c2VkIGlmIHRoZSBvcHRpb24gQG9wdGlvbnst
+LWJhdGNofQpoYXMgYWxzbyBiZWVuIGdpdmVuLiAgVGhpcyBpcyBkaWZmZXJlbnQg
+ZnJvbSBHbnVQRyB2ZXJzaW9uIDEueC4KCkBpdGVtIC0tcGluZW50cnktbW9kZSBA
+Y29kZXttb2RlfQpAb3BpbmRleCBwaW5lbnRyeS1tb2RlClNldCB0aGUgcGluZW50
+cnkgbW9kZSB0byBAY29kZXttb2RlfS4gIEFsbG93ZWQgdmFsdWVzIGZvciBAY29k
+ZXttb2RlfQphcmU6CkB0YWJsZSBAYXNpcwogIEBpdGVtIGRlZmF1bHQKICBVc2Ug
+dGhlIGRlZmF1bHQgb2YgdGhlIGFnZW50LCB3aGljaCBpcyBAY29kZXthc2t9Lgog
+IEBpdGVtIGFzawogIEZvcmNlIHRoZSB1c2Ugb2YgdGhlIFBpbmVudHJ5LgogIEBp
+dGVtIGNhbmNlbAogIEVtdWxhdGUgdXNlIG9mIFBpbmVudHJ5J3MgY2FuY2VsIGJ1
+dHRvbi4KICBAaXRlbSBlcnJvcgogIFJldHVybiBhIFBpbmVudHJ5IGVycm9yIChg
+YE5vIFBpbmVudHJ5JycpLgogIEBpdGVtIGxvb3BiYWNrCiAgUmVkaXJlY3QgUGlu
+ZW50cnkgcXVlcmllcyB0byB0aGUgY2FsbGVyLiAgTm90ZSB0aGF0IGluIGNvbnRy
+YXN0IHRvCiAgUGluZW50cnkgdGhlIHVzZXIgaXMgbm90IHByb21wdGVkIGFnYWlu
+IGlmIGhlIGVudGVycyBhIGJhZCBwYXNzd29yZC4KQGVuZCB0YWJsZQoKQGl0ZW0g
+LS1jb21tYW5kLWZkIEBjb2Rle259CkBvcGluZGV4IGNvbW1hbmQtZmQKVGhpcyBp
+cyBhIHJlcGxhY2VtZW50IGZvciB0aGUgZGVwcmVjYXRlZCBzaGFyZWQtbWVtb3J5
+IElQQyBtb2RlLgpJZiB0aGlzIG9wdGlvbiBpcyBlbmFibGVkLCB1c2VyIGlucHV0
+IG9uIHF1ZXN0aW9ucyBpcyBub3QgZXhwZWN0ZWQKZnJvbSB0aGUgVFRZIGJ1dCBm
+cm9tIHRoZSBnaXZlbiBmaWxlIGRlc2NyaXB0b3IuIEl0IHNob3VsZCBiZSB1c2Vk
+CnRvZ2V0aGVyIHdpdGggQG9wdGlvbnstLXN0YXR1cy1mZH0uIFNlZSB0aGUgZmls
+ZSBkb2MvREVUQUlMUyBpbiB0aGUgc291cmNlCmRpc3RyaWJ1dGlvbiBmb3IgZGV0
+YWlscyBvbiBob3cgdG8gdXNlIGl0LgoKQGl0ZW0gLS1jb21tYW5kLWZpbGUgQGNv
+ZGV7ZmlsZX0KQG9waW5kZXggY29tbWFuZC1maWxlClNhbWUgYXMgQG9wdGlvbnst
+LWNvbW1hbmQtZmR9LCBleGNlcHQgdGhlIGNvbW1hbmRzIGFyZSByZWFkIG91dCBv
+ZiBmaWxlCkBjb2Rle2ZpbGV9CgpAaXRlbSAtLWFsbG93LW5vbi1zZWxmc2lnbmVk
+LXVpZApAaXRlbXggLS1uby1hbGxvdy1ub24tc2VsZnNpZ25lZC11aWQKQG9waW5k
+ZXggYWxsb3ctbm9uLXNlbGZzaWduZWQtdWlkCkFsbG93IHRoZSBpbXBvcnQgYW5k
+IHVzZSBvZiBrZXlzIHdpdGggdXNlciBJRHMgd2hpY2ggYXJlIG5vdApzZWxmLXNp
+Z25lZC4gVGhpcyBpcyBub3QgcmVjb21tZW5kZWQsIGFzIGEgbm9uIHNlbGYtc2ln
+bmVkIHVzZXIgSUQgaXMKdHJpdmlhbCB0byBmb3JnZS4gQG9wdGlvbnstLW5vLWFs
+bG93LW5vbi1zZWxmc2lnbmVkLXVpZH0gZGlzYWJsZXMuCgpAaXRlbSAtLWFsbG93
+LWZyZWVmb3JtLXVpZApAb3BpbmRleCBhbGxvdy1mcmVlZm9ybS11aWQKRGlzYWJs
+ZSBhbGwgY2hlY2tzIG9uIHRoZSBmb3JtIG9mIHRoZSB1c2VyIElEIHdoaWxlIGdl
+bmVyYXRpbmcgYSBuZXcKb25lLiBUaGlzIG9wdGlvbiBzaG91bGQgb25seSBiZSB1
+c2VkIGluIHZlcnkgc3BlY2lhbCBlbnZpcm9ubWVudHMgYXMKaXQgZG9lcyBub3Qg
+ZW5zdXJlIHRoZSBkZS1mYWN0byBzdGFuZGFyZCBmb3JtYXQgb2YgdXNlciBJRHMu
+CgpAaXRlbSAtLWlnbm9yZS10aW1lLWNvbmZsaWN0CkBvcGluZGV4IGlnbm9yZS10
+aW1lLWNvbmZsaWN0CkdudVBHIG5vcm1hbGx5IGNoZWNrcyB0aGF0IHRoZSB0aW1l
+c3RhbXBzIGFzc29jaWF0ZWQgd2l0aCBrZXlzIGFuZApzaWduYXR1cmVzIGhhdmUg
+cGxhdXNpYmxlIHZhbHVlcy4gSG93ZXZlciwgc29tZXRpbWVzIGEgc2lnbmF0dXJl
+CnNlZW1zIHRvIGJlIG9sZGVyIHRoYW4gdGhlIGtleSBkdWUgdG8gY2xvY2sgcHJv
+YmxlbXMuIFRoaXMgb3B0aW9uCm1ha2VzIHRoZXNlIGNoZWNrcyBqdXN0IGEgd2Fy
+bmluZy4gU2VlIGFsc28gQG9wdGlvbnstLWlnbm9yZS12YWxpZC1mcm9tfSBmb3IK
+dGltZXN0YW1wIGlzc3VlcyBvbiBzdWJrZXlzLgoKQGl0ZW0gLS1pZ25vcmUtdmFs
+aWQtZnJvbQpAb3BpbmRleCBpZ25vcmUtdmFsaWQtZnJvbQpHbnVQRyBub3JtYWxs
+eSBkb2VzIG5vdCBzZWxlY3QgYW5kIHVzZSBzdWJrZXlzIGNyZWF0ZWQgaW4gdGhl
+IGZ1dHVyZS4KVGhpcyBvcHRpb24gYWxsb3dzIHRoZSB1c2Ugb2Ygc3VjaCBrZXlz
+IGFuZCB0aHVzIGV4aGliaXRzIHRoZQpwcmUtMS4wLjcgYmVoYXZpb3VyLiBZb3Ug
+c2hvdWxkIG5vdCB1c2UgdGhpcyBvcHRpb24gdW5sZXNzIHRoZXJlCmlzIHNvbWUg
+Y2xvY2sgcHJvYmxlbS4gU2VlIGFsc28gQG9wdGlvbnstLWlnbm9yZS10aW1lLWNv
+bmZsaWN0fSBmb3IgdGltZXN0YW1wCmlzc3VlcyB3aXRoIHNpZ25hdHVyZXMuCgpA
+aXRlbSAtLWlnbm9yZS1jcmMtZXJyb3IKQG9waW5kZXggaWdub3JlLWNyYy1lcnJv
+cgpUaGUgQVNDSUkgYXJtb3IgdXNlZCBieSBPcGVuUEdQIGlzIHByb3RlY3RlZCBi
+eSBhIENSQyBjaGVja3N1bSBhZ2FpbnN0CnRyYW5zbWlzc2lvbiBlcnJvcnMuIE9j
+Y2FzaW9uYWxseSB0aGUgQ1JDIGdldHMgbWFuZ2xlZCBzb21ld2hlcmUgb24KdGhl
+IHRyYW5zbWlzc2lvbiBjaGFubmVsIGJ1dCB0aGUgYWN0dWFsIGNvbnRlbnQgKHdo
+aWNoIGlzIHByb3RlY3RlZCBieQp0aGUgT3BlblBHUCBwcm90b2NvbCBhbnl3YXkp
+IGlzIHN0aWxsIG9rYXkuIFRoaXMgb3B0aW9uIGFsbG93cyBHbnVQRwp0byBpZ25v
+cmUgQ1JDIGVycm9ycy4KCkBpdGVtIC0taWdub3JlLW1kYy1lcnJvcgpAb3BpbmRl
+eCBpZ25vcmUtbWRjLWVycm9yClRoaXMgb3B0aW9uIGNoYW5nZXMgYSBNREMgaW50
+ZWdyaXR5IHByb3RlY3Rpb24gZmFpbHVyZSBpbnRvIGEgd2FybmluZy4KVGhpcyBj
+YW4gYmUgdXNlZnVsIGlmIGEgbWVzc2FnZSBpcyBwYXJ0aWFsbHkgY29ycnVwdCwg
+YnV0IGl0IGlzCm5lY2Vzc2FyeSB0byBnZXQgYXMgbXVjaCBkYXRhIGFzIHBvc3Np
+YmxlIG91dCBvZiB0aGUgY29ycnVwdCBtZXNzYWdlLgpIb3dldmVyLCBiZSBhd2Fy
+ZSB0aGF0IGEgTURDIHByb3RlY3Rpb24gZmFpbHVyZSBtYXkgYWxzbyBtZWFuIHRo
+YXQgdGhlCm1lc3NhZ2Ugd2FzIHRhbXBlcmVkIHdpdGggaW50ZW50aW9uYWxseSBi
+eSBhbiBhdHRhY2tlci4KCkBpdGVtIC0tYWxsb3ctd2Vhay1kaWdlc3QtYWxnb3MK
+QG9waW5kZXggYWxsb3ctd2Vhay1kaWdlc3QtYWxnb3MKU2lnbmF0dXJlcyBtYWRl
+IHdpdGgga25vd24td2VhayBkaWdlc3QgYWxnb3JpdGhtcyBhcmUgbm9ybWFsbHkK
+cmVqZWN0ZWQgd2l0aCBhbiBgYGludmFsaWQgZGlnZXN0IGFsZ29yaXRobScnIG1l
+c3NhZ2UuICBUaGlzIG9wdGlvbgphbGxvd3MgdGhlIHZlcmlmaWNhdGlvbiBvZiBz
+aWduYXR1cmVzIG1hZGUgd2l0aCBzdWNoIHdlYWsgYWxnb3JpdGhtcy4KTUQ1IGlz
+IHRoZSBvbmx5IGRpZ2VzdCBhbGdvcml0aG0gY29uc2lkZXJlZCB3ZWFrIGJ5IGRl
+ZmF1bHQuICBTZWUgYWxzbwpAb3B0aW9uey0td2Vhay1kaWdlc3R9IHRvIHJlamVj
+dCBvdGhlciBkaWdlc3QgYWxnb3JpdGhtcy4KCkBpdGVtIC0td2Vhay1kaWdlc3Qg
+QGNvZGV7bmFtZX0KQG9waW5kZXggd2Vhay1kaWdlc3QKVHJlYXQgdGhlIHNwZWNp
+ZmllZCBkaWdlc3QgYWxnb3JpdGhtIGFzIHdlYWsuICBTaWduYXR1cmVzIG1hZGUg
+b3Zlcgp3ZWFrIGRpZ2VzdHMgYWxnb3JpdGhtcyBhcmUgbm9ybWFsbHkgcmVqZWN0
+ZWQuIFRoaXMgb3B0aW9uIGNhbiBiZQpzdXBwbGllZCBtdWx0aXBsZSB0aW1lcyBp
+ZiBtdWx0aXBsZSBhbGdvcml0aG1zIHNob3VsZCBiZSBjb25zaWRlcmVkCndlYWsu
+ICBTZWUgYWxzbyBAb3B0aW9uey0tYWxsb3ctd2Vhay1kaWdlc3QtYWxnb3N9IHRv
+IGRpc2FibGUKcmVqZWN0aW9uIG9mIHdlYWsgZGlnZXN0cy4gIE1ENSBpcyBhbHdh
+eXMgY29uc2lkZXJlZCB3ZWFrLCBhbmQgZG9lcwpub3QgbmVlZCB0byBiZSBsaXN0
+ZWQgZXhwbGljaXRseS4KCkBpdGVtIC0tbm8tZGVmYXVsdC1rZXlyaW5nCkBvcGlu
+ZGV4IG5vLWRlZmF1bHQta2V5cmluZwpEbyBub3QgYWRkIHRoZSBkZWZhdWx0IGtl
+eXJpbmdzIHRvIHRoZSBsaXN0IG9mIGtleXJpbmdzLiBOb3RlIHRoYXQKR251UEcg
+d2lsbCBub3Qgb3BlcmF0ZSB3aXRob3V0IGFueSBrZXlyaW5ncywgc28gaWYgeW91
+IHVzZSB0aGlzIG9wdGlvbgphbmQgZG8gbm90IHByb3ZpZGUgYWx0ZXJuYXRlIGtl
+eXJpbmdzIHZpYSBAb3B0aW9uey0ta2V5cmluZ30gb3IKQG9wdGlvbnstLXNlY3Jl
+dC1rZXlyaW5nfSwgdGhlbiBHbnVQRyB3aWxsIHN0aWxsIHVzZSB0aGUgZGVmYXVs
+dCBwdWJsaWMgb3IKc2VjcmV0IGtleXJpbmdzLgoKQGl0ZW0gLS1za2lwLXZlcmlm
+eQpAb3BpbmRleCBza2lwLXZlcmlmeQpTa2lwIHRoZSBzaWduYXR1cmUgdmVyaWZp
+Y2F0aW9uIHN0ZXAuIFRoaXMgbWF5IGJlCnVzZWQgdG8gbWFrZSB0aGUgZGVjcnlw
+dGlvbiBmYXN0ZXIgaWYgdGhlIHNpZ25hdHVyZQp2ZXJpZmljYXRpb24gaXMgbm90
+IG5lZWRlZC4KCkBpdGVtIC0td2l0aC1rZXktZGF0YQpAb3BpbmRleCB3aXRoLWtl
+eS1kYXRhClByaW50IGtleSBsaXN0aW5ncyBkZWxpbWl0ZWQgYnkgY29sb25zIChs
+aWtlIEBvcHRpb257LS13aXRoLWNvbG9uc30pIGFuZApwcmludCB0aGUgcHVibGlj
+IGtleSBkYXRhLgoKQGl0ZW0gLS1mYXN0LWxpc3QtbW9kZQpAb3BpbmRleCBmYXN0
+LWxpc3QtbW9kZQpDaGFuZ2VzIHRoZSBvdXRwdXQgb2YgdGhlIGxpc3QgY29tbWFu
+ZHMgdG8gd29yayBmYXN0ZXI7IHRoaXMgaXMgYWNoaWV2ZWQKYnkgbGVhdmluZyBz
+b21lIHBhcnRzIGVtcHR5LiBTb21lIGFwcGxpY2F0aW9ucyBkb24ndCBuZWVkIHRo
+ZSB1c2VyIElECmFuZCB0aGUgdHJ1c3QgaW5mb3JtYXRpb24gZ2l2ZW4gaW4gdGhl
+IGxpc3RpbmdzLiBCeSB1c2luZyB0aGlzIG9wdGlvbnMKdGhleSBjYW4gZ2V0IGEg
+ZmFzdGVyIGxpc3RpbmcuIFRoZSBleGFjdCBiZWhhdmlvdXIgb2YgdGhpcyBvcHRp
+b24gbWF5CmNoYW5nZSBpbiBmdXR1cmUgdmVyc2lvbnMuICBJZiB5b3UgYXJlIG1p
+c3Npbmcgc29tZSBpbmZvcm1hdGlvbiwgZG9uJ3QKdXNlIHRoaXMgb3B0aW9uLgoK
+QGl0ZW0gLS1uby1saXRlcmFsCkBvcGluZGV4IG5vLWxpdGVyYWwKVGhpcyBpcyBu
+b3QgZm9yIG5vcm1hbCB1c2UuIFVzZSB0aGUgc291cmNlIHRvIHNlZSBmb3Igd2hh
+dCBpdCBtaWdodCBiZSB1c2VmdWwuCgpAaXRlbSAtLXNldC1maWxlc2l6ZQpAb3Bp
+bmRleCBzZXQtZmlsZXNpemUKVGhpcyBpcyBub3QgZm9yIG5vcm1hbCB1c2UuIFVz
+ZSB0aGUgc291cmNlIHRvIHNlZSBmb3Igd2hhdCBpdCBtaWdodCBiZSB1c2VmdWwu
+CgpAaXRlbSAtLXNob3ctc2Vzc2lvbi1rZXkKQG9waW5kZXggc2hvdy1zZXNzaW9u
+LWtleQpEaXNwbGF5IHRoZSBzZXNzaW9uIGtleSB1c2VkIGZvciBvbmUgbWVzc2Fn
+ZS4gU2VlCkBvcHRpb257LS1vdmVycmlkZS1zZXNzaW9uLWtleX0gZm9yIHRoZSBj
+b3VudGVycGFydCBvZiB0aGlzIG9wdGlvbi4KCldlIHRoaW5rIHRoYXQgS2V5IEVz
+Y3JvdyBpcyBhIEJhZCBUaGluZzsgaG93ZXZlciB0aGUgdXNlciBzaG91bGQgaGF2
+ZQp0aGUgZnJlZWRvbSB0byBkZWNpZGUgd2hldGhlciB0byBnbyB0byBwcmlzb24g
+b3IgdG8gcmV2ZWFsIHRoZSBjb250ZW50Cm9mIG9uZSBzcGVjaWZpYyBtZXNzYWdl
+IHdpdGhvdXQgY29tcHJvbWlzaW5nIGFsbCBtZXNzYWdlcyBldmVyCmVuY3J5cHRl
+ZCBmb3Igb25lIHNlY3JldCBrZXkuCgpZb3UgY2FuIGFsc28gdXNlIHRoaXMgb3B0
+aW9uIGlmIHlvdSByZWNlaXZlIGFuIGVuY3J5cHRlZCBtZXNzYWdlIHdoaWNoCmlz
+IGFidXNpdmUgb3Igb2ZmZW5zaXZlLCB0byBwcm92ZSB0byB0aGUgYWRtaW5pc3Ry
+YXRvcnMgb2YgdGhlCm1lc3NhZ2luZyBzeXN0ZW0gdGhhdCB0aGUgY2lwaGVydGV4
+dCB0cmFuc21pdHRlZCBjb3JyZXNwb25kcyB0byBhbgppbmFwcHJvcHJpYXRlIHBs
+YWludGV4dCBzbyB0aGV5IGNhbiB0YWtlIGFjdGlvbiBhZ2FpbnN0IHRoZSBvZmZl
+bmRpbmcKdXNlci4KCkBpdGVtIC0tb3ZlcnJpZGUtc2Vzc2lvbi1rZXkgQGNvZGV7
+c3RyaW5nfQpAb3BpbmRleCBvdmVycmlkZS1zZXNzaW9uLWtleQpEb24ndCB1c2Ug
+dGhlIHB1YmxpYyBrZXkgYnV0IHRoZSBzZXNzaW9uIGtleSBAY29kZXtzdHJpbmd9
+LiBUaGUgZm9ybWF0Cm9mIHRoaXMgc3RyaW5nIGlzIHRoZSBzYW1lIGFzIHRoZSBv
+bmUgcHJpbnRlZCBieQpAb3B0aW9uey0tc2hvdy1zZXNzaW9uLWtleX0uIFRoaXMg
+b3B0aW9uIGlzIG5vcm1hbGx5IG5vdCB1c2VkIGJ1dCBjb21lcwpoYW5keSBpbiBj
+YXNlIHNvbWVvbmUgZm9yY2VzIHlvdSB0byByZXZlYWwgdGhlIGNvbnRlbnQgb2Yg
+YW4gZW5jcnlwdGVkCm1lc3NhZ2U7IHVzaW5nIHRoaXMgb3B0aW9uIHlvdSBjYW4g
+ZG8gdGhpcyB3aXRob3V0IGhhbmRpbmcgb3V0IHRoZQpzZWNyZXQga2V5LgoKQGl0
+ZW0gLS1hc2stc2lnLWV4cGlyZQpAaXRlbXggLS1uby1hc2stc2lnLWV4cGlyZQpA
+b3BpbmRleCBhc2stc2lnLWV4cGlyZQpXaGVuIG1ha2luZyBhIGRhdGEgc2lnbmF0
+dXJlLCBwcm9tcHQgZm9yIGFuIGV4cGlyYXRpb24gdGltZS4gSWYgdGhpcwpvcHRp
+b24gaXMgbm90IHNwZWNpZmllZCwgdGhlIGV4cGlyYXRpb24gdGltZSBzZXQgdmlh
+CkBvcHRpb257LS1kZWZhdWx0LXNpZy1leHBpcmV9IGlzIHVzZWQuIEBvcHRpb257
+LS1uby1hc2stc2lnLWV4cGlyZX0KZGlzYWJsZXMgdGhpcyBvcHRpb24uCgpAaXRl
+bSAtLWRlZmF1bHQtc2lnLWV4cGlyZQpAb3BpbmRleCBkZWZhdWx0LXNpZy1leHBp
+cmUKVGhlIGRlZmF1bHQgZXhwaXJhdGlvbiB0aW1lIHRvIHVzZSBmb3Igc2lnbmF0
+dXJlIGV4cGlyYXRpb24uIFZhbGlkCnZhbHVlcyBhcmUgIjAiIGZvciBubyBleHBp
+cmF0aW9uLCBhIG51bWJlciBmb2xsb3dlZCBieSB0aGUgbGV0dGVyIGQKKGZvciBk
+YXlzKSwgdyAoZm9yIHdlZWtzKSwgbSAoZm9yIG1vbnRocyksIG9yIHkgKGZvciB5
+ZWFycykgKGZvcgpleGFtcGxlICIybSIgZm9yIHR3byBtb250aHMsIG9yICI1eSIg
+Zm9yIGZpdmUgeWVhcnMpLCBvciBhbiBhYnNvbHV0ZQpkYXRlIGluIHRoZSBmb3Jt
+IFlZWVktTU0tREQuIERlZmF1bHRzIHRvICIwIi4KCkBpdGVtIC0tYXNrLWNlcnQt
+ZXhwaXJlCkBpdGVteCAtLW5vLWFzay1jZXJ0LWV4cGlyZQpAb3BpbmRleCBhc2st
+Y2VydC1leHBpcmUKV2hlbiBtYWtpbmcgYSBrZXkgc2lnbmF0dXJlLCBwcm9tcHQg
+Zm9yIGFuIGV4cGlyYXRpb24gdGltZS4gSWYgdGhpcwpvcHRpb24gaXMgbm90IHNw
+ZWNpZmllZCwgdGhlIGV4cGlyYXRpb24gdGltZSBzZXQgdmlhCkBvcHRpb257LS1k
+ZWZhdWx0LWNlcnQtZXhwaXJlfSBpcyB1c2VkLiBAb3B0aW9uey0tbm8tYXNrLWNl
+cnQtZXhwaXJlfQpkaXNhYmxlcyB0aGlzIG9wdGlvbi4KCkBpdGVtIC0tZGVmYXVs
+dC1jZXJ0LWV4cGlyZQpAb3BpbmRleCBkZWZhdWx0LWNlcnQtZXhwaXJlClRoZSBk
+ZWZhdWx0IGV4cGlyYXRpb24gdGltZSB0byB1c2UgZm9yIGtleSBzaWduYXR1cmUg
+ZXhwaXJhdGlvbi4KVmFsaWQgdmFsdWVzIGFyZSAiMCIgZm9yIG5vIGV4cGlyYXRp
+b24sIGEgbnVtYmVyIGZvbGxvd2VkIGJ5IHRoZQpsZXR0ZXIgZCAoZm9yIGRheXMp
+LCB3IChmb3Igd2Vla3MpLCBtIChmb3IgbW9udGhzKSwgb3IgeSAoZm9yIHllYXJz
+KQooZm9yIGV4YW1wbGUgIjJtIiBmb3IgdHdvIG1vbnRocywgb3IgIjV5IiBmb3Ig
+Zml2ZSB5ZWFycyksIG9yIGFuCmFic29sdXRlIGRhdGUgaW4gdGhlIGZvcm0gWVlZ
+WS1NTS1ERC4gRGVmYXVsdHMgdG8gIjAiLgoKQGl0ZW0gLS1hbGxvdy1zZWNyZXQt
+a2V5LWltcG9ydApAb3BpbmRleCBhbGxvdy1zZWNyZXQta2V5LWltcG9ydApUaGlz
+IGlzIGFuIG9ic29sZXRlIG9wdGlvbiBhbmQgaXMgbm90IHVzZWQgYW55d2hlcmUu
+CgpAaXRlbSAtLWFsbG93LW11bHRpcGxlLW1lc3NhZ2VzCkBpdGVtIC0tbm8tYWxs
+b3ctbXVsdGlwbGUtbWVzc2FnZXMKQG9waW5kZXggYWxsb3ctbXVsdGlwbGUtbWVz
+c2FnZXMKQWxsb3cgcHJvY2Vzc2luZyBvZiBtdWx0aXBsZSBPcGVuUEdQIG1lc3Nh
+Z2VzIGNvbnRhaW5lZCBpbiBhIHNpbmdsZSBmaWxlCm9yIHN0cmVhbS4gIFNvbWUg
+cHJvZ3JhbXMgdGhhdCBjYWxsIEdQRyBhcmUgbm90IHByZXBhcmVkIHRvIGRlYWwg
+d2l0aAptdWx0aXBsZSBtZXNzYWdlcyBiZWluZyBwcm9jZXNzZWQgdG9nZXRoZXIs
+IHNvIHRoaXMgb3B0aW9uIGRlZmF1bHRzIHRvCm5vLiAgTm90ZSB0aGF0IHZlcnNp
+b25zIG9mIEdQRyBwcmlvciB0byAxLjQuNyBhbHdheXMgYWxsb3dlZCBtdWx0aXBs
+ZQptZXNzYWdlcy4KCldhcm5pbmc6IERvIG5vdCB1c2UgdGhpcyBvcHRpb24gdW5s
+ZXNzIHlvdSBuZWVkIGl0IGFzIGEgdGVtcG9yYXJ5Cndvcmthcm91bmQhCgoKQGl0
+ZW0gLS1lbmFibGUtc3BlY2lhbC1maWxlbmFtZXMKQG9waW5kZXggZW5hYmxlLXNw
+ZWNpYWwtZmlsZW5hbWVzClRoaXMgb3B0aW9ucyBlbmFibGVzIGEgbW9kZSBpbiB3
+aGljaCBmaWxlbmFtZXMgb2YgdGhlIGZvcm0KQGZpbGV7LSZufSwgd2hlcmUgbiBp
+cyBhIG5vbi1uZWdhdGl2ZSBkZWNpbWFsIG51bWJlciwKcmVmZXIgdG8gdGhlIGZp
+bGUgZGVzY3JpcHRvciBuIGFuZCBub3QgdG8gYSBmaWxlIHdpdGggdGhhdCBuYW1l
+LgoKQGl0ZW0gLS1uby1leHBlbnNpdmUtdHJ1c3QtY2hlY2tzCkBvcGluZGV4IG5v
+LWV4cGVuc2l2ZS10cnVzdC1jaGVja3MKRXhwZXJpbWVudGFsIHVzZSBvbmx5LgoK
+QGl0ZW0gLS1wcmVzZXJ2ZS1wZXJtaXNzaW9ucwpAb3BpbmRleCBwcmVzZXJ2ZS1w
+ZXJtaXNzaW9ucwpEb24ndCBjaGFuZ2UgdGhlIHBlcm1pc3Npb25zIG9mIGEgc2Vj
+cmV0IGtleXJpbmcgYmFjayB0byB1c2VyCnJlYWQvd3JpdGUgb25seS4gVXNlIHRo
+aXMgb3B0aW9uIG9ubHkgaWYgeW91IHJlYWxseSBrbm93IHdoYXQgeW91IGFyZSBk
+b2luZy4KCkBpdGVtIC0tZGVmYXVsdC1wcmVmZXJlbmNlLWxpc3QgQGNvZGV7c3Ry
+aW5nfQpAb3BpbmRleCBkZWZhdWx0LXByZWZlcmVuY2UtbGlzdApTZXQgdGhlIGxp
+c3Qgb2YgZGVmYXVsdCBwcmVmZXJlbmNlcyB0byBAY29kZXtzdHJpbmd9LiBUaGlz
+IHByZWZlcmVuY2UKbGlzdCBpcyB1c2VkIGZvciBuZXcga2V5cyBhbmQgYmVjb21l
+cyB0aGUgZGVmYXVsdCBmb3IgInNldHByZWYiIGluIHRoZQplZGl0IG1lbnUuCgpA
+aXRlbSAtLWRlZmF1bHQta2V5c2VydmVyLXVybCBAY29kZXtuYW1lfQpAb3BpbmRl
+eCBkZWZhdWx0LWtleXNlcnZlci11cmwKU2V0IHRoZSBkZWZhdWx0IGtleXNlcnZl
+ciBVUkwgdG8gQGNvZGV7bmFtZX0uIFRoaXMga2V5c2VydmVyIHdpbGwgYmUKdXNl
+ZCBhcyB0aGUga2V5c2VydmVyIFVSTCB3aGVuIHdyaXRpbmcgYSBuZXcgc2VsZi1z
+aWduYXR1cmUgb24gYSBrZXksCndoaWNoIGluY2x1ZGVzIGtleSBnZW5lcmF0aW9u
+IGFuZCBjaGFuZ2luZyBwcmVmZXJlbmNlcy4KCkBpdGVtIC0tbGlzdC1jb25maWcK
+QG9waW5kZXggbGlzdC1jb25maWcKRGlzcGxheSB2YXJpb3VzIGludGVybmFsIGNv
+bmZpZ3VyYXRpb24gcGFyYW1ldGVycyBvZiBHbnVQRy4gVGhpcyBvcHRpb24KaXMg
+aW50ZW5kZWQgZm9yIGV4dGVybmFsIHByb2dyYW1zIHRoYXQgY2FsbCBHbnVQRyB0
+byBwZXJmb3JtIHRhc2tzLCBhbmQKaXMgdGh1cyBub3QgZ2VuZXJhbGx5IHVzZWZ1
+bC4gU2VlIHRoZSBmaWxlIEBmaWxle2RvYy9ERVRBSUxTfSBpbiB0aGUKc291cmNl
+IGRpc3RyaWJ1dGlvbiBmb3IgdGhlIGRldGFpbHMgb2Ygd2hpY2ggY29uZmlndXJh
+dGlvbiBpdGVtcyBtYXkgYmUKbGlzdGVkLiBAb3B0aW9uey0tbGlzdC1jb25maWd9
+IGlzIG9ubHkgdXNhYmxlIHdpdGgKQG9wdGlvbnstLXdpdGgtY29sb25zfSBzZXQu
+CgpAaXRlbSAtLWxpc3QtZ2NyeXB0LWNvbmZpZwpAb3BpbmRleCBsaXN0LWdjcnlw
+dC1jb25maWcKRGlzcGxheSB2YXJpb3VzIGludGVybmFsIGNvbmZpZ3VyYXRpb24g
+cGFyYW1ldGVycyBvZiBMaWJnY3J5cHQuCgpAaXRlbSAtLWdwZ2NvbmYtbGlzdApA
+b3BpbmRleCBncGdjb25mLWxpc3QKVGhpcyBjb21tYW5kIGlzIHNpbWlsYXIgdG8g
+QG9wdGlvbnstLWxpc3QtY29uZmlnfSBidXQgaW4gZ2VuZXJhbCBvbmx5CmludGVy
+bmFsbHkgdXNlZCBieSB0aGUgQGNvbW1hbmR7Z3BnY29uZn0gdG9vbC4KCkBpdGVt
+IC0tZ3BnY29uZi10ZXN0CkBvcGluZGV4IGdwZ2NvbmYtdGVzdApUaGlzIGlzIG1v
+cmUgb3IgbGVzcyBkdW1teSBhY3Rpb24uICBIb3dldmVyIGl0IHBhcnNlcyB0aGUg
+Y29uZmlndXJhdGlvbgpmaWxlIGFuZCByZXR1cm5zIHdpdGggZmFpbHVyZSBpZiB0
+aGUgY29uZmlndXJhdGlvbiBmaWxlIHdvdWxkIHByZXZlbnQKQGNvbW1hbmR7Z3Bn
+fSBmcm9tIHN0YXJ0dXAuICBUaHVzIGl0IG1heSBiZSB1c2VkIHRvIHJ1biBhIHN5
+bnRheCBjaGVjawpvbiB0aGUgY29uZmlndXJhdGlvbiBmaWxlLgoKQGVuZCB0YWJs
+ZQoKQGMgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpAYyAqKioqKioq
+IERlcHJlY2F0ZWQgKioqKioqKioqKioqCkBjICoqKioqKioqKioqKioqKioqKioq
+KioqKioqKioqKioKQG5vZGUgRGVwcmVjYXRlZCBPcHRpb25zCkBzdWJzZWN0aW9u
+IERlcHJlY2F0ZWQgb3B0aW9ucwoKQHRhYmxlIEBnbnVwZ3RhYm9wdAoKQGl0ZW0g
+LS1zaG93LXBob3RvcwpAaXRlbXggLS1uby1zaG93LXBob3RvcwpAb3BpbmRleCBz
+aG93LXBob3RvcwpDYXVzZXMgQG9wdGlvbnstLWxpc3Qta2V5c30sIEBvcHRpb257
+LS1saXN0LXNpZ3N9LApAb3B0aW9uey0tbGlzdC1wdWJsaWMta2V5c30sIEBvcHRp
+b257LS1saXN0LXNlY3JldC1rZXlzfSwgYW5kIHZlcmlmeWluZwphIHNpZ25hdHVy
+ZSB0byBhbHNvIGRpc3BsYXkgdGhlIHBob3RvIElEIGF0dGFjaGVkIHRvIHRoZSBr
+ZXksIGlmCmFueS4gU2VlIGFsc28gQG9wdGlvbnstLXBob3RvLXZpZXdlcn0uIFRo
+ZXNlIG9wdGlvbnMgYXJlIGRlcHJlY2F0ZWQuIFVzZQpAb3B0aW9uey0tbGlzdC1v
+cHRpb25zIFtuby1dc2hvdy1waG90b3N9IGFuZC9vciBAb3B0aW9uey0tdmVyaWZ5
+LW9wdGlvbnMKW25vLV1zaG93LXBob3Rvc30gaW5zdGVhZC4KCkBpdGVtIC0tc2hv
+dy1rZXlyaW5nCkBvcGluZGV4IHNob3cta2V5cmluZwpEaXNwbGF5IHRoZSBrZXly
+aW5nIG5hbWUgYXQgdGhlIGhlYWQgb2Yga2V5IGxpc3RpbmdzIHRvIHNob3cgd2hp
+Y2gKa2V5cmluZyBhIGdpdmVuIGtleSByZXNpZGVzIG9uLiBUaGlzIG9wdGlvbiBp
+cyBkZXByZWNhdGVkOiB1c2UKQG9wdGlvbnstLWxpc3Qtb3B0aW9ucyBbbm8tXXNo
+b3cta2V5cmluZ30gaW5zdGVhZC4KCkBpdGVtIC0tYWx3YXlzLXRydXN0CkBvcGlu
+ZGV4IGFsd2F5cy10cnVzdApJZGVudGljYWwgdG8gQG9wdGlvbnstLXRydXN0LW1v
+ZGVsIGFsd2F5c30uIFRoaXMgb3B0aW9uIGlzIGRlcHJlY2F0ZWQuCgpAaXRlbSAt
+LXNob3ctbm90YXRpb24KQGl0ZW14IC0tbm8tc2hvdy1ub3RhdGlvbgpAb3BpbmRl
+eCBzaG93LW5vdGF0aW9uClNob3cgc2lnbmF0dXJlIG5vdGF0aW9ucyBpbiB0aGUg
+QG9wdGlvbnstLWxpc3Qtc2lnc30gb3IgQG9wdGlvbnstLWNoZWNrLXNpZ3N9IGxp
+c3RpbmdzCmFzIHdlbGwgYXMgd2hlbiB2ZXJpZnlpbmcgYSBzaWduYXR1cmUgd2l0
+aCBhIG5vdGF0aW9uIGluIGl0LiBUaGVzZQpvcHRpb25zIGFyZSBkZXByZWNhdGVk
+LiBVc2UgQG9wdGlvbnstLWxpc3Qtb3B0aW9ucyBbbm8tXXNob3ctbm90YXRpb259
+CmFuZC9vciBAb3B0aW9uey0tdmVyaWZ5LW9wdGlvbnMgW25vLV1zaG93LW5vdGF0
+aW9ufSBpbnN0ZWFkLgoKQGl0ZW0gLS1zaG93LXBvbGljeS11cmwKQGl0ZW14IC0t
+bm8tc2hvdy1wb2xpY3ktdXJsCkBvcGluZGV4IHNob3ctcG9saWN5LXVybApTaG93
+IHBvbGljeSBVUkxzIGluIHRoZSBAb3B0aW9uey0tbGlzdC1zaWdzfSBvciBAb3B0
+aW9uey0tY2hlY2stc2lnc30KbGlzdGluZ3MgYXMgd2VsbCBhcyB3aGVuIHZlcmlm
+eWluZyBhIHNpZ25hdHVyZSB3aXRoIGEgcG9saWN5IFVSTCBpbgppdC4gVGhlc2Ug
+b3B0aW9ucyBhcmUgZGVwcmVjYXRlZC4gVXNlIEBvcHRpb257LS1saXN0LW9wdGlv
+bnMKW25vLV1zaG93LXBvbGljeS11cmx9IGFuZC9vciBAb3B0aW9uey0tdmVyaWZ5
+LW9wdGlvbnMKW25vLV1zaG93LXBvbGljeS11cmx9IGluc3RlYWQuCgoKQGVuZCB0
+YWJsZQoKCkBjICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
+KioqKioKQGMgKioqKioqKioqKioqKioqICAgICAgICAgICAgKioqKioqKioqKioq
+KioqKgpAYyAqKioqKioqKioqKioqKiogICBGSUxFUyAgICAqKioqKioqKioqKioq
+KioqCkBjICoqKioqKioqKioqKioqKiAgICAgICAgICAgICoqKioqKioqKioqKioq
+KioKQGMgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
+KgpAbWFuc2VjdCBmaWxlcwpAbm9kZSBHUEcgQ29uZmlndXJhdGlvbgpAc2VjdGlv
+biBDb25maWd1cmF0aW9uIGZpbGVzCgpUaGVyZSBhcmUgYSBmZXcgY29uZmlndXJh
+dGlvbiBmaWxlcyB0byBjb250cm9sIGNlcnRhaW4gYXNwZWN0cyBvZgpAY29tbWFu
+ZHtAZ3BnbmFtZX0ncyBvcGVyYXRpb24uIFVubGVzcyBub3RlZCwgdGhleSBhcmUg
+ZXhwZWN0ZWQgaW4gdGhlCmN1cnJlbnQgaG9tZSBkaXJlY3RvcnkgKEBweHJlZntv
+cHRpb24gLS1ob21lZGlyfSkuCgpAdGFibGUgQGZpbGUKCiAgQGl0ZW0gZ3BnLmNv
+bmYKICBAY2luZGV4IGdwZy5jb25mCiAgVGhpcyBpcyB0aGUgc3RhbmRhcmQgY29u
+ZmlndXJhdGlvbiBmaWxlIHJlYWQgYnkgQGNvbW1hbmR7QGdwZ25hbWV9IG9uCiAg
+c3RhcnR1cC4gIEl0IG1heSBjb250YWluIGFueSB2YWxpZCBsb25nIG9wdGlvbjsg
+dGhlIGxlYWRpbmcgdHdvIGRhc2hlcwogIG1heSBub3QgYmUgZW50ZXJlZCBhbmQg
+dGhlIG9wdGlvbiBtYXkgbm90IGJlIGFiYnJldmlhdGVkLiAgVGhpcyBkZWZhdWx0
+CiAgbmFtZSBtYXkgYmUgY2hhbmdlZCBvbiB0aGUgY29tbWFuZCBsaW5lIChAcHhy
+ZWZ7Z3BnLW9wdGlvbiAtLW9wdGlvbnN9KS4KICBZb3Ugc2hvdWxkIGJhY2t1cCB0
+aGlzIGZpbGUuCgpAZW5kIHRhYmxlCgpAYyBtYW46LlJFCk5vdGUgdGhhdCBvbiBs
+YXJnZXIgaW5zdGFsbGF0aW9ucywgaXQgaXMgdXNlZnVsIHRvIHB1dCBwcmVkZWZp
+bmVkIGZpbGVzCmludG8gdGhlIGRpcmVjdG9yeSBAZmlsZXtAdmFsdWV7U1lTQ09O
+RlNLRUxESVJ9fSBzbyB0aGF0Cm5ld2x5IGNyZWF0ZWQgdXNlcnMgc3RhcnQgdXAg
+d2l0aCBhIHdvcmtpbmcgY29uZmlndXJhdGlvbi4KRm9yIGV4aXN0aW5nIHVzZXJz
+IGEgc21hbGwKaGVscGVyIHNjcmlwdCBpcyBwcm92aWRlZCB0byBjcmVhdGUgdGhl
+c2UgZmlsZXMgKEBweHJlZnthZGRnbnVwZ2hvbWV9KS4KCkZvciBpbnRlcm5hbCBw
+dXJwb3NlcyBAY29tbWFuZHtAZ3BnbmFtZX0gY3JlYXRlcyBhbmQgbWFpbnRhaW5z
+IGEgZmV3IG90aGVyCmZpbGVzOyBUaGV5IGFsbCBsaXZlIGluIGluIHRoZSBjdXJy
+ZW50IGhvbWUgZGlyZWN0b3J5IChAcHhyZWZ7b3B0aW9uCi0taG9tZWRpcn0pLiAg
+T25seSB0aGUgQGNvbW1hbmR7QGdwZ25hbWV9IHByb2dyYW0gbWF5IG1vZGlmeSB0
+aGVzZSBmaWxlcy4KCgpAdGFibGUgQGZpbGUKICBAaXRlbSB+Ly5nbnVwZy9wdWJy
+aW5nLmdwZwogIFRoZSBwdWJsaWMga2V5cmluZy4gIFlvdSBzaG91bGQgYmFja3Vw
+IHRoaXMgZmlsZS4KCiAgQGl0ZW0gfi8uZ251cGcvcHVicmluZy5ncGcubG9jawog
+IFRoZSBsb2NrIGZpbGUgZm9yIHRoZSBwdWJsaWMga2V5cmluZy4KCiAgQGl0ZW0g
+fi8uZ251cGcvcHVicmluZy5rYngKICBUaGUgcHVibGljIGtleXJpbmcgdXNpbmcg
+YSBkaWZmZXJlbnQgZm9ybWF0LiAgVGhpcyBmaWxlIGlzIHNoYXJyZWQKICB3aXRo
+IEBjb21tYW5ke2dwZ3NtfS4gIFlvdSBzaG91bGQgYmFja3VwIHRoaXMgZmlsZS4K
+CiAgQGl0ZW0gfi8uZ251cGcvcHVicmluZy5rYngubG9jawogIFRoZSBsb2NrIGZp
+bGUgZm9yIEBmaWxle3B1YnJpbmcua2J4fS4KCiAgQGl0ZW0gfi8uZ251cGcvc2Vj
+cmluZy5ncGcKICBBIHNlY3JldCBrZXlyaW5nIGFzIHVzZWQgYnkgR251UEcgdmVy
+c2lvbnMgYmVmb3JlIDIuMS4gIEl0IGlzIG5vdAogIHVzZWQgYnkgR251UEcgMi4x
+IGFuZCBsYXRlci4KCiAgQGl0ZW0gfi8uZ251cGcvLmdwZy12MjEtbWlncmF0ZWQK
+ICBGaWxlIGluZGljYXRpbmcgdGhhdCBhIG1pZ3JhdGlvbiB0byBHbnVQRyAyLjEg
+aGFzIGJlZW4gZG9uZS4KCiAgQGl0ZW0gfi8uZ251cGcvdHJ1c3RkYi5ncGcKICBU
+aGUgdHJ1c3QgZGF0YWJhc2UuICBUaGVyZSBpcyBubyBuZWVkIHRvIGJhY2t1cCB0
+aGlzIGZpbGU7IGl0IGlzIGJldHRlcgogIHRvIGJhY2t1cCB0aGUgb3duZXJ0cnVz
+dCB2YWx1ZXMgKEBweHJlZntvcHRpb24gLS1leHBvcnQtb3duZXJ0cnVzdH0pLgoK
+ICBAaXRlbSB+Ly5nbnVwZy90cnVzdGRiLmdwZy5sb2NrCiAgVGhlIGxvY2sgZmls
+ZSBmb3IgdGhlIHRydXN0IGRhdGFiYXNlLgoKICBAaXRlbSB+Ly5nbnVwZy9yYW5k
+b21fc2VlZAogIEEgZmlsZSB1c2VkIHRvIHByZXNlcnZlIHRoZSBzdGF0ZSBvZiB0
+aGUgaW50ZXJuYWwgcmFuZG9tIHBvb2wuCgogIEBpdGVtIH4vLmdudXBnL3NlY3Jp
+bmcuZ3BnLmxvY2sKICBUaGUgbG9jayBmaWxlIGZvciB0aGUgc2VjcmV0IGtleXJp
+bmcuCgogIEBpdGVtIH4vLmdudXBnL29wZW5wZ3AtcmV2b2NzLmQvCiAgVGhpcyBp
+cyB0aGUgZGlyZWN0b3J5IHdoZXJlIGdwZyBzdG9yZXMgcHJlLWdlbmVyYXRlZCBy
+ZXZvY2F0aW9uCiAgY2VydGlmaWNhdGVzLiAgVGhlIGZpbGUgbmFtZSBjb3JyZXNw
+b25kcyB0byB0aGUgT3BlblBHUCBmaW5nZXJwcmludCBvZgogIHRoZSByZXNwZWN0
+aXZlIGtleS4gIEl0IGlzIHN1Z2dlc3RlZCB0byBiYWNrdXAgdGhvc2UgY2VydGlm
+aWNhdGVzIGFuZAogIGlmIHRoZSBwcmltYXJ5IHByaXZhdGUga2V5IGlzIG5vdCBz
+dG9yZWQgb24gdGhlIGRpc2sgdG8gbW92ZSB0aGVtIHRvCiAgYW4gZXh0ZXJuYWwg
+c3RvcmFnZSBkZXZpY2UuICBBbnlvbmUgd2hvIGNhbiBhY2Nlc3MgdGhlc2VzIGZp
+bGVzIGlzCiAgYWJsZSB0byByZXZva2UgdGhlIGNvcnJlc3BvbmRpbmcga2V5LiAg
+WW91IG1heSB3YW50IHRvIHByaW50IHRoZW0gb3V0LgogIFlvdSBzaG91bGQgYmFj
+a3VwIGFsbCBmaWxlcyBpbiB0aGlzIGRpcmVjdG9yeSBhbmQgdGFrZSBjYXJlIHRv
+IGtlZXAKICB0aGlzIGJhY2t1cCBjbG9zZWQgYXdheS4KCiAgQGl0ZW0gQHZhbHVl
+e0RBVEFESVJ9L29wdGlvbnMuc2tlbAogIFRoZSBza2VsZXRvbiBvcHRpb25zIGZp
+bGUuCgogIEBpdGVtIEB2YWx1ZXtMSUJESVJ9LwogIERlZmF1bHQgbG9jYXRpb24g
+Zm9yIGV4dGVuc2lvbnMuCgpAZW5kIHRhYmxlCgpAYyBtYW46LlJFCk9wZXJhdGlv
+biBpcyBmdXJ0aGVyIGNvbnRyb2xsZWQgYnkgYSBmZXcgZW52aXJvbm1lbnQgdmFy
+aWFibGVzOgoKQHRhYmxlIEBhc2lzCgogIEBpdGVtIEhPTUUKICBVc2VkIHRvIGxv
+Y2F0ZSB0aGUgZGVmYXVsdCBob21lIGRpcmVjdG9yeS4KCiAgQGl0ZW0gR05VUEdI
+T01FCiAgSWYgc2V0IGRpcmVjdG9yeSB1c2VkIGluc3RlYWQgb2YgIn4vLmdudXBn
+Ii4KCiAgQGl0ZW0gR1BHX0FHRU5UX0lORk8KICBUaGlzIHZhcmlhYmxlIHdhcyB1
+c2VkIGJ5IEdudVBHIHZlcnNpb25zIGJlZm9yZSAyLjEKCiAgQGl0ZW0gUElORU5U
+UllfVVNFUl9EQVRBCiAgVGhpcyB2YWx1ZSBpcyBwYXNzZWQgdmlhIGdwZy1hZ2Vu
+dCB0byBwaW5lbnRyeS4gIEl0IGlzIHVzZWZ1bCB0byBjb252ZXkKICBleHRyYSBp
+bmZvcm1hdGlvbiB0byBhIGN1c3RvbSBwaW5lbnRyeS4KCiAgQGl0ZW0gQ09MVU1O
+UwogIEBpdGVteCBMSU5FUwogIFVzZWQgdG8gc2l6ZSBzb21lIGRpc3BsYXlzIHRv
+IHRoZSBmdWxsIHNpemUgb2YgdGhlIHNjcmVlbi4KCgogIEBpdGVtIExBTkdVQUdF
+CiAgQXBhcnQgZnJvbSBpdHMgdXNlIGJ5IEdOVSwgaXQgaXMgdXNlZCBpbiB0aGUg
+VzMyIHZlcnNpb24gdG8gb3ZlcnJpZGUgdGhlCiAgbGFuZ3VhZ2Ugc2VsZWN0aW9u
+IGRvbmUgdGhyb3VnaCB0aGUgUmVnaXN0cnkuICBJZiB1c2VkIGFuZCBzZXQgdG8g
+YQogIHZhbGlkIGFuZCBhdmFpbGFibGUgbGFuZ3VhZ2UgbmFtZSAoQHZhcntsYW5n
+aWR9KSwgdGhlIGZpbGUgd2l0aCB0aGUKICB0cmFuc2xhdGlvbiBpcyBsb2FkZWQg
+ZnJvbQoKICBAY29kZXtAdmFye2dwZ2Rpcn0vZ251cGcubmxzL0B2YXJ7bGFuZ2lk
+fS5tb30uICBIZXJlIEB2YXJ7Z3BnZGlyfSBpcyB0aGUKICBkaXJlY3Rvcnkgb3V0
+IG9mIHdoaWNoIHRoZSBncGcgYmluYXJ5IGhhcyBiZWVuIGxvYWRlZC4gIElmIGl0
+IGNhbid0IGJlCiAgbG9hZGVkIHRoZSBSZWdpc3RyeSBpcyB0cmllZCBhbmQgYXMg
+bGFzdCByZXNvcnQgdGhlIG5hdGl2ZSBXaW5kb3dzCiAgbG9jYWxlIHN5c3RlbSBp
+cyB1c2VkLgoKQGVuZCB0YWJsZQoKCkBjICoqKioqKioqKioqKioqKioqKioqKioq
+KioqKioqKioqKioqKioqKioqKioKQGMgKioqKioqKioqKioqKioqICAgICAgICAg
+ICAgKioqKioqKioqKioqKioqKgpAYyAqKioqKioqKioqKioqKiogIEVYQU1QTEVT
+ICAqKioqKioqKioqKioqKioqCkBjICoqKioqKioqKioqKioqKiAgICAgICAgICAg
+ICoqKioqKioqKioqKioqKioKQGMgKioqKioqKioqKioqKioqKioqKioqKioqKioq
+KioqKioqKioqKioqKioqKgpAbWFuc2VjdCBleGFtcGxlcwpAbm9kZSBHUEcgRXhh
+bXBsZXMKQHNlY3Rpb24gRXhhbXBsZXMKCkB0YWJsZSBAYXNpcwoKQGl0ZW0gZ3Bn
+IC1zZSAtciBAY29kZXtCb2J9IEBjb2Rle2ZpbGV9CnNpZ24gYW5kIGVuY3J5cHQg
+Zm9yIHVzZXIgQm9iCgpAaXRlbSBncGcgLS1jbGVhcnNpZ24gQGNvZGV7ZmlsZX0K
+bWFrZSBhIGNsZWFyIHRleHQgc2lnbmF0dXJlCgpAaXRlbSBncGcgLXNiIEBjb2Rl
+e2ZpbGV9Cm1ha2UgYSBkZXRhY2hlZCBzaWduYXR1cmUKCkBpdGVtIGdwZyAtdSAw
+eDEyMzQ1Njc4IC1zYiBAY29kZXtmaWxlfQptYWtlIGEgZGV0YWNoZWQgc2lnbmF0
+dXJlIHdpdGggdGhlIGtleSAweDEyMzQ1Njc4CgpAaXRlbSBncGcgLS1saXN0LWtl
+eXMgQGNvZGV7dXNlcl9JRH0Kc2hvdyBrZXlzCgpAaXRlbSBncGcgLS1maW5nZXJw
+cmludCBAY29kZXt1c2VyX0lEfQpzaG93IGZpbmdlcnByaW50CgpAaXRlbSBncGcg
+LS12ZXJpZnkgQGNvZGV7cGdwZmlsZX0KQGl0ZW14IGdwZyAtLXZlcmlmeSBAY29k
+ZXtzaWdmaWxlfQpWZXJpZnkgdGhlIHNpZ25hdHVyZSBvZiB0aGUgZmlsZSBidXQg
+ZG8gbm90IG91dHB1dCB0aGUgZGF0YS4gVGhlCnNlY29uZCBmb3JtIGlzIHVzZWQg
+Zm9yIGRldGFjaGVkIHNpZ25hdHVyZXMsIHdoZXJlIEBjb2Rle3NpZ2ZpbGV9Cmlz
+IHRoZSBkZXRhY2hlZCBzaWduYXR1cmUgKGVpdGhlciBBU0NJSSBhcm1vcmVkIG9y
+IGJpbmFyeSkgYW5kCmFyZSB0aGUgc2lnbmVkIGRhdGE7IGlmIHRoaXMgaXMgbm90
+IGdpdmVuLCB0aGUgbmFtZSBvZgp0aGUgZmlsZSBob2xkaW5nIHRoZSBzaWduZWQg
+ZGF0YSBpcyBjb25zdHJ1Y3RlZCBieSBjdXR0aW5nIG9mZiB0aGUKZXh0ZW5zaW9u
+ICgiLmFzYyIgb3IgIi5zaWciKSBvZiBAY29kZXtzaWdmaWxlfSBvciBieSBhc2tp
+bmcgdGhlCnVzZXIgZm9yIHRoZSBmaWxlbmFtZS4KQGVuZCB0YWJsZQoKCkBjICoq
+KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKQGMgKioq
+KioqKioqKioqKioqICAgICAgICAgICAgKioqKioqKioqKioqKioqKgpAYyAqKioq
+KioqKioqKioqKiogIFVTRVIgSUQgICAqKioqKioqKioqKioqKioqCkBjICoqKioq
+KioqKioqKioqKiAgICAgICAgICAgICoqKioqKioqKioqKioqKioKQGMgKioqKioq
+KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgpAbWFuc2VjdCBo
+b3cgdG8gc3BlY2lmeSBhIHVzZXIgaWQKQGlmc2V0IGlzbWFuCkBpbmNsdWRlIHNw
+ZWNpZnktdXNlci1pZC50ZXhpCkBlbmQgaWZzZXQKCkBtYW5zZWN0IHJldHVybiB2
+YWx1ZQpAY2hhcGhlYWRpbmcgUkVUVVJOIFZBTFVFCgpUaGUgcHJvZ3JhbSByZXR1
+cm5zIDAgaWYgZXZlcnl0aGluZyB3YXMgZmluZSwgMSBpZiBhdCBsZWFzdAphIHNp
+Z25hdHVyZSB3YXMgYmFkLCBhbmQgb3RoZXIgZXJyb3IgY29kZXMgZm9yIGZhdGFs
+IGVycm9ycy4KCkBtYW5zZWN0IHdhcm5pbmdzCkBjaGFwaGVhZGluZyBXQVJOSU5H
+UwoKVXNlIGEgKmdvb2QqIHBhc3N3b3JkIGZvciB5b3VyIHVzZXIgYWNjb3VudCBh
+bmQgYSAqZ29vZCogcGFzc3BocmFzZQp0byBwcm90ZWN0IHlvdXIgc2VjcmV0IGtl
+eS4gVGhpcyBwYXNzcGhyYXNlIGlzIHRoZSB3ZWFrZXN0IHBhcnQgb2YgdGhlCndo
+b2xlIHN5c3RlbS4gUHJvZ3JhbXMgdG8gZG8gZGljdGlvbmFyeSBhdHRhY2tzIG9u
+IHlvdXIgc2VjcmV0IGtleXJpbmcKYXJlIHZlcnkgZWFzeSB0byB3cml0ZSBhbmQg
+c28geW91IHNob3VsZCBwcm90ZWN0IHlvdXIgIn4vLmdudXBnLyIKZGlyZWN0b3J5
+IHZlcnkgd2VsbC4KCktlZXAgaW4gbWluZCB0aGF0LCBpZiB0aGlzIHByb2dyYW0g
+aXMgdXNlZCBvdmVyIGEgbmV0d29yayAodGVsbmV0KSwgaXQKaXMgKnZlcnkqIGVh
+c3kgdG8gc3B5IG91dCB5b3VyIHBhc3NwaHJhc2UhCgpJZiB5b3UgYXJlIGdvaW5n
+IHRvIHZlcmlmeSBkZXRhY2hlZCBzaWduYXR1cmVzLCBtYWtlIHN1cmUgdGhhdCB0
+aGUKcHJvZ3JhbSBrbm93cyBhYm91dCBpdDsgZWl0aGVyIGdpdmUgYm90aCBmaWxl
+bmFtZXMgb24gdGhlIGNvbW1hbmQgbGluZQpvciB1c2UgQHNhbXB7LX0gdG8gc3Bl
+Y2lmeSBTVERJTi4KCkBtYW5zZWN0IGludGVyb3BlcmFiaWxpdHkKQGNoYXBoZWFk
+aW5nIElOVEVST1BFUkFCSUxJVFkgV0lUSCBPVEhFUiBPUEVOUEdQIFBST0dSQU1T
+CgpHbnVQRyB0cmllcyB0byBiZSBhIHZlcnkgZmxleGlibGUgaW1wbGVtZW50YXRp
+b24gb2YgdGhlIE9wZW5QR1AKc3RhbmRhcmQuIEluIHBhcnRpY3VsYXIsIEdudVBH
+IGltcGxlbWVudHMgbWFueSBvZiB0aGUgb3B0aW9uYWwgcGFydHMKb2YgdGhlIHN0
+YW5kYXJkLCBzdWNoIGFzIHRoZSBTSEEtNTEyIGhhc2gsIGFuZCB0aGUgWkxJQiBh
+bmQgQlpJUDIKY29tcHJlc3Npb24gYWxnb3JpdGhtcy4gSXQgaXMgaW1wb3J0YW50
+IHRvIGJlIGF3YXJlIHRoYXQgbm90IGFsbApPcGVuUEdQIHByb2dyYW1zIGltcGxl
+bWVudCB0aGVzZSBvcHRpb25hbCBhbGdvcml0aG1zIGFuZCB0aGF0IGJ5CmZvcmNp
+bmcgdGhlaXIgdXNlIHZpYSB0aGUgQG9wdGlvbnstLWNpcGhlci1hbGdvfSwKQG9w
+dGlvbnstLWRpZ2VzdC1hbGdvfSwgQG9wdGlvbnstLWNlcnQtZGlnZXN0LWFsZ299
+LCBvcgpAb3B0aW9uey0tY29tcHJlc3MtYWxnb30gb3B0aW9ucyBpbiBHbnVQRywg
+aXQgaXMgcG9zc2libGUgdG8gY3JlYXRlIGEKcGVyZmVjdGx5IHZhbGlkIE9wZW5Q
+R1AgbWVzc2FnZSwgYnV0IG9uZSB0aGF0IGNhbm5vdCBiZSByZWFkIGJ5IHRoZQpp
+bnRlbmRlZCByZWNpcGllbnQuCgpUaGVyZSBhcmUgZG96ZW5zIG9mIHZhcmlhdGlv
+bnMgb2YgT3BlblBHUCBwcm9ncmFtcyBhdmFpbGFibGUsIGFuZCBlYWNoCnN1cHBv
+cnRzIGEgc2xpZ2h0bHkgZGlmZmVyZW50IHN1YnNldCBvZiB0aGVzZSBvcHRpb25h
+bCBhbGdvcml0aG1zLgpGb3IgZXhhbXBsZSwgdW50aWwgcmVjZW50bHksIG5vICh1
+bmhhY2tlZCkgdmVyc2lvbiBvZiBQR1Agc3VwcG9ydGVkCnRoZSBCTE9XRklTSCBj
+aXBoZXIgYWxnb3JpdGhtLiBBIG1lc3NhZ2UgdXNpbmcgQkxPV0ZJU0ggc2ltcGx5
+IGNvdWxkCm5vdCBiZSByZWFkIGJ5IGEgUEdQIHVzZXIuIEJ5IGRlZmF1bHQsIEdu
+dVBHIHVzZXMgdGhlIHN0YW5kYXJkCk9wZW5QR1AgcHJlZmVyZW5jZXMgc3lzdGVt
+IHRoYXQgd2lsbCBhbHdheXMgZG8gdGhlIHJpZ2h0IHRoaW5nIGFuZApjcmVhdGUg
+bWVzc2FnZXMgdGhhdCBhcmUgdXNhYmxlIGJ5IGFsbCByZWNpcGllbnRzLCByZWdh
+cmRsZXNzIG9mIHdoaWNoCk9wZW5QR1AgcHJvZ3JhbSB0aGV5IHVzZS4gT25seSBv
+dmVycmlkZSB0aGlzIHNhZmUgZGVmYXVsdCBpZiB5b3UKcmVhbGx5IGtub3cgd2hh
+dCB5b3UgYXJlIGRvaW5nLgoKSWYgeW91IGFic29sdXRlbHkgbXVzdCBvdmVycmlk
+ZSB0aGUgc2FmZSBkZWZhdWx0LCBvciBpZiB0aGUgcHJlZmVyZW5jZXMKb24gYSBn
+aXZlbiBrZXkgYXJlIGludmFsaWQgZm9yIHNvbWUgcmVhc29uLCB5b3UgYXJlIGZh
+ciBiZXR0ZXIgb2ZmIHVzaW5nCnRoZSBAb3B0aW9uey0tcGdwNn0sIEBvcHRpb257
+LS1wZ3A3fSwgb3IgQG9wdGlvbnstLXBncDh9IG9wdGlvbnMuIFRoZXNlCm9wdGlv
+bnMgYXJlIHNhZmUgYXMgdGhleSBkbyBub3QgZm9yY2UgYW55IHBhcnRpY3VsYXIg
+YWxnb3JpdGhtcyBpbgp2aW9sYXRpb24gb2YgT3BlblBHUCwgYnV0IHJhdGhlciBy
+ZWR1Y2UgdGhlIGF2YWlsYWJsZSBhbGdvcml0aG1zIHRvIGEKIlBHUC1zYWZlIiBs
+aXN0LgoKQG1hbnNlY3QgYnVncwpAY2hhcGhlYWRpbmcgQlVHUwoKT24gb2xkZXIg
+c3lzdGVtcyB0aGlzIHByb2dyYW0gc2hvdWxkIGJlIGluc3RhbGxlZCBhcyBzZXR1
+aWQocm9vdCkuIFRoaXMKaXMgbmVjZXNzYXJ5IHRvIGxvY2sgbWVtb3J5IHBhZ2Vz
+LiBMb2NraW5nIG1lbW9yeSBwYWdlcyBwcmV2ZW50cyB0aGUKb3BlcmF0aW5nIHN5
+c3RlbSBmcm9tIHdyaXRpbmcgbWVtb3J5IHBhZ2VzICh3aGljaCBtYXkgY29udGFp
+bgpwYXNzcGhyYXNlcyBvciBvdGhlciBzZW5zaXRpdmUgbWF0ZXJpYWwpIHRvIGRp
+c2suIElmIHlvdSBnZXQgbm8Kd2FybmluZyBtZXNzYWdlIGFib3V0IGluc2VjdXJl
+IG1lbW9yeSB5b3VyIG9wZXJhdGluZyBzeXN0ZW0gc3VwcG9ydHMKbG9ja2luZyB3
+aXRob3V0IGJlaW5nIHJvb3QuIFRoZSBwcm9ncmFtIGRyb3BzIHJvb3QgcHJpdmls
+ZWdlcyBhcyBzb29uCmFzIGxvY2tlZCBtZW1vcnkgaXMgYWxsb2NhdGVkLgoKTm90
+ZSBhbHNvIHRoYXQgc29tZSBzeXN0ZW1zIChlc3BlY2lhbGx5IGxhcHRvcHMpIGhh
+dmUgdGhlIGFiaWxpdHkgdG8KYGBzdXNwZW5kIHRvIGRpc2snJyAoYWxzbyBrbm93
+biBhcyBgYHNhZmUgc2xlZXAnJyBvciBgYGhpYmVybmF0ZScnKS4KVGhpcyB3cml0
+ZXMgYWxsIG1lbW9yeSB0byBkaXNrIGJlZm9yZSBnb2luZyBpbnRvIGEgbG93IHBv
+d2VyIG9yIGV2ZW4KcG93ZXJlZCBvZmYgbW9kZS4gIFVubGVzcyBtZWFzdXJlcyBh
+cmUgdGFrZW4gaW4gdGhlIG9wZXJhdGluZyBzeXN0ZW0KdG8gcHJvdGVjdCB0aGUg
+c2F2ZWQgbWVtb3J5LCBwYXNzcGhyYXNlcyBvciBvdGhlciBzZW5zaXRpdmUgbWF0
+ZXJpYWwKbWF5IGJlIHJlY292ZXJhYmxlIGZyb20gaXQgbGF0ZXIuCgpCZWZvcmUg
+eW91IHJlcG9ydCBhIGJ1ZyB5b3Ugc2hvdWxkIGZpcnN0IHNlYXJjaCB0aGUgbWFp
+bGluZyBsaXN0CmFyY2hpdmVzIGZvciBzaW1pbGFyIHByb2JsZW1zIGFuZCBzZWNv
+bmQgY2hlY2sgd2hldGhlciBzdWNoIGEgYnVnIGhhcwphbHJlYWR5IGJlZW4gcmVw
+b3J0ZWQgdG8gb3VyIGJ1ZyB0cmFja2VyIGF0IGh0dHA6Ly9idWdzLmdudXBnLm9y
+ZyAuCgpAYyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
+KioqCkBjICoqKioqKioqKioqKioqKiAgICAgICAgICAgICAgKioqKioqKioqKioq
+KioKQGMgKioqKioqKioqKioqKioqICBVTkFUVEVOREVEICAqKioqKioqKioqKioq
+KgpAYyAqKioqKioqKioqKioqKiogICAgICAgICAgICAgICoqKioqKioqKioqKioq
+CkBjICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioK
+QG1hbnBhdXNlCkBub2RlIFVuYXR0ZW5kZWQgVXNhZ2Ugb2YgR1BHCkBzZWN0aW9u
+IFVuYXR0ZW5kZWQgVXNhZ2UKCkBjb21tYW5ke2dwZ30gaXMgb2Z0ZW4gdXNlZCBh
+cyBhIGJhY2tlbmQgZW5naW5lIGJ5IG90aGVyIHNvZnR3YXJlLiAgVG8gaGVscAp3
+aXRoIHRoaXMgYSBtYWNoaW5lIGludGVyZmFjZSBoYXMgYmVlbiBkZWZpbmVkIHRv
+IGhhdmUgYW4gdW5hbWJpZ3VvdXMKd2F5IHRvIGRvIHRoaXMuICBUaGUgb3B0aW9u
+cyBAb3B0aW9uey0tc3RhdHVzLWZkfSBhbmQgQG9wdGlvbnstLWJhdGNofQphcmUg
+YWxtb3N0IGFsd2F5cyByZXF1aXJlZCBmb3IgdGhpcy4KCkBtZW51CiogVW5hdHRl
+bmRlZCBHUEcga2V5IGdlbmVyYXRpb246OiAgVW5hdHRlbmRlZCBrZXkgZ2VuZXJh
+dGlvbgpAZW5kIG1lbnUKCgpAbm9kZSBVbmF0dGVuZGVkIEdQRyBrZXkgZ2VuZXJh
+dGlvbgpAc3Vic2VjdGlvbiBVbmF0dGVuZGVkIGtleSBnZW5lcmF0aW9uCgpUaGUg
+Y29tbWFuZCBAb3B0aW9uey0tZ2VuLWtleX0gbWF5IGJlIHVzZWQgYWxvbmcgd2l0
+aCB0aGUgb3B0aW9uCkBvcHRpb257LS1iYXRjaH0gZm9yIHVuYXR0ZW5kZWQga2V5
+IGdlbmVyYXRpb24uICBUaGUgcGFyYW1ldGVycyBhcmUKZWl0aGVyIHJlYWQgZnJv
+bSBzdGRpbiBvciBnaXZlbiBhcyBhIGZpbGUgb24gdGhlIGNvbW1hbmQgbGluZS4K
+VGhlIGZvcm1hdCBvZiB0aGUgcGFyYW1ldGVyIGZpbGUgaXMgYXMgZm9sbG93czoK
+CkBpdGVtaXplIEBidWxsZXQKICBAaXRlbSBUZXh0IG9ubHksIGxpbmUgbGVuZ3Ro
+IGlzIGxpbWl0ZWQgdG8gYWJvdXQgMTAwMCBjaGFyYWN0ZXJzLgogIEBpdGVtIFVU
+Ri04IGVuY29kaW5nIG11c3QgYmUgdXNlZCB0byBzcGVjaWZ5IG5vbi1BU0NJSSBj
+aGFyYWN0ZXJzLgogIEBpdGVtIEVtcHR5IGxpbmVzIGFyZSBpZ25vcmVkLgogIEBp
+dGVtIExlYWRpbmcgYW5kIHRyYWlsaW5nIHdoaWxlIHNwYWNlIGlzIGlnbm9yZWQu
+CiAgQGl0ZW0gQSBoYXNoIHNpZ24gYXMgdGhlIGZpcnN0IG5vbiB3aGl0ZSBzcGFj
+ZSBjaGFyYWN0ZXIgaW5kaWNhdGVzCiAgYSBjb21tZW50IGxpbmUuCiAgQGl0ZW0g
+Q29udHJvbCBzdGF0ZW1lbnRzIGFyZSBpbmRpY2F0ZWQgYnkgYSBsZWFkaW5nIHBl
+cmNlbnQgc2lnbiwgdGhlCiAgYXJndW1lbnRzIGFyZSBzZXBhcmF0ZWQgYnkgd2hp
+dGUgc3BhY2UgZnJvbSB0aGUga2V5d29yZC4KICBAaXRlbSBQYXJhbWV0ZXJzIGFy
+ZSBzcGVjaWZpZWQgYnkgYSBrZXl3b3JkLCBmb2xsb3dlZCBieSBhIGNvbG9uLiAg
+QXJndW1lbnRzCiAgYXJlIHNlcGFyYXRlZCBieSB3aGl0ZSBzcGFjZS4KICBAaXRl
+bQogIFRoZSBmaXJzdCBwYXJhbWV0ZXIgbXVzdCBiZSBAc2FtcHtLZXktVHlwZX07
+IGNvbnRyb2wgc3RhdGVtZW50cyBtYXkgYmUKICBwbGFjZWQgYW55d2hlcmUuCiAg
+QGl0ZW0KICBUaGUgb3JkZXIgb2YgdGhlIHBhcmFtZXRlcnMgZG9lcyBub3QgbWF0
+dGVyIGV4Y2VwdCBmb3IgQHNhbXB7S2V5LVR5cGV9CiAgd2hpY2ggbXVzdCBiZSB0
+aGUgZmlyc3QgcGFyYW1ldGVyLiAgVGhlIHBhcmFtZXRlcnMgYXJlIG9ubHkgdXNl
+ZCBmb3IKICB0aGUgZ2VuZXJhdGVkIGtleWJsb2NrIChwcmltYXJ5IGFuZCBzdWJr
+ZXlzKTsgcGFyYW1ldGVycyBmcm9tIHByZXZpb3VzCiAgc2V0cyBhcmUgbm90IHVz
+ZWQuICBTb21lIHN5bnRhY3RpY2FsbHkgY2hlY2tzIG1heSBiZSBwZXJmb3JtZWQu
+CiAgQGl0ZW0KICBLZXkgZ2VuZXJhdGlvbiB0YWtlcyBwbGFjZSB3aGVuIGVpdGhl
+ciB0aGUgZW5kIG9mIHRoZSBwYXJhbWV0ZXIgZmlsZQogIGlzIHJlYWNoZWQsIHRo
+ZSBuZXh0IEBzYW1we0tleS1UeXBlfSBwYXJhbWV0ZXIgaXMgZW5jb3VudGVyZWQg
+b3IgYXQgdGhlCiAgY29udHJvbCBzdGF0ZW1lbnQgQHNhbXB7JWNvbW1pdH0gaXMg
+ZW5jb3VudGVyZWQuCkBlbmQgaXRlbWl6ZQoKQG5vaW5kZW50CkNvbnRyb2wgc3Rh
+dGVtZW50czoKCkB0YWJsZSBAYXNpcwoKQGl0ZW0gJWVjaG8gQHZhcnt0ZXh0fQpQ
+cmludCBAdmFye3RleHR9IGFzIGRpYWdub3N0aWMuCgpAaXRlbSAlZHJ5LXJ1bgpT
+dXBwcmVzcyBhY3R1YWwga2V5IGdlbmVyYXRpb24gKHVzZWZ1bCBmb3Igc3ludGF4
+IGNoZWNraW5nKS4KCkBpdGVtICVjb21taXQKUGVyZm9ybSB0aGUga2V5IGdlbmVy
+YXRpb24uICBOb3RlIHRoYXQgYW4gaW1wbGljaXQgY29tbWl0IGlzIGRvbmUgYXQK
+dGhlIG5leHQgQGFzaXN7S2V5LVR5cGV9IHBhcmFtZXRlci4KCkBpdGVtICVwdWJy
+aW5nIEB2YXJ7ZmlsZW5hbWV9CkBpdGVteCAlc2VjcmluZyBAdmFye2ZpbGVuYW1l
+fQpEbyBub3Qgd3JpdGUgdGhlIGtleSB0byB0aGUgZGVmYXVsdCBvciBjb21tYW5k
+bGluZSBnaXZlbiBrZXlyaW5nIGJ1dAp0byBAdmFye2ZpbGVuYW1lfS4gIFRoaXMg
+bXVzdCBiZSBnaXZlbiBiZWZvcmUgdGhlIGZpcnN0IGNvbW1pdCB0byB0YWtlCnBs
+YWNlLCBkdXBsaWNhdGUgc3BlY2lmaWNhdGlvbiBvZiB0aGUgc2FtZSBmaWxlbmFt
+ZSBpcyBpZ25vcmVkLCB0aGUKbGFzdCBmaWxlbmFtZSBiZWZvcmUgYSBjb21taXQg
+aXMgdXNlZC4gIFRoZSBmaWxlbmFtZSBpcyB1c2VkIHVudGlsIGEKbmV3IGZpbGVu
+YW1lIGlzIHVzZWQgKGF0IGNvbW1pdCBwb2ludHMpIGFuZCBhbGwga2V5cyBhcmUg
+d3JpdHRlbiB0bwp0aGF0IGZpbGUuIElmIGEgbmV3IGZpbGVuYW1lIGlzIGdpdmVu
+LCB0aGlzIGZpbGUgaXMgY3JlYXRlZCAoYW5kCm92ZXJ3cml0ZXMgYW4gZXhpc3Rp
+bmcgb25lKS4gIEZvciBHbnVQRyB2ZXJzaW9ucyBwcmlvciB0byAyLjEsIGJvdGgK
+Y29udHJvbCBzdGF0ZW1lbnRzIG11c3QgYmUgZ2l2ZW4uIEZvciBHbnVQRyAyLjEg
+YW5kIGxhdGVyCkBzYW1weyVzZWNyaW5nfSBpcyBhIG5vLW9wLgoKQGl0ZW0gJWFz
+ay1wYXNzcGhyYXNlCkBpdGVteCAlbm8tYXNrLXBhc3NwaHJhc2UKVGhpcyBvcHRp
+b24gaXMgYSBuby1vcCBmb3IgR251UEcgMi4xIGFuZCBsYXRlci4KCkBpdGVtICVu
+by1wcm90ZWN0aW9uClVzaW5nIHRoaXMgb3B0aW9uIGFsbG93cyB0aGUgY3JlYXRp
+b24gb2Yga2V5cyB3aXRob3V0IGFueSBwYXNzcGhyYXNlCnByb3RlY3Rpb24uICBU
+aGlzIG9wdGlvbiBpcyBtYWlubHkgaW50ZW5kZWQgZm9yIHJlZ3Jlc3Npb24gdGVz
+dHMuCgpAaXRlbSAldHJhbnNpZW50LWtleQpJZiBnaXZlbiB0aGUga2V5cyBhcmUg
+Y3JlYXRlZCB1c2luZyBhIGZhc3RlciBhbmQgYSBzb21ld2hhdCBsZXNzCnNlY3Vy
+ZSByYW5kb20gbnVtYmVyIGdlbmVyYXRvci4gIFRoaXMgb3B0aW9uIG1heSBiZSB1
+c2VkIGZvciBrZXlzCndoaWNoIGFyZSBvbmx5IHVzZWQgZm9yIGEgc2hvcnQgdGlt
+ZSBhbmQgZG8gbm90IHJlcXVpcmUgZnVsbApjcnlwdG9ncmFwaGljIHN0cmVuZ3Ro
+LiAgSXQgdGFrZXMgb25seSBlZmZlY3QgaWYgdXNlZCB0b2dldGhlciB3aXRoCnRo
+ZSBjb250cm9sIHN0YXRlbWVudCBAc2FtcHslbm8tcHJvdGVjdGlvbn0uCgpAZW5k
+IHRhYmxlCgpAbm9pbmRlbnQKR2VuZXJhbCBQYXJhbWV0ZXJzOgoKQHRhYmxlIEBh
+c2lzCgpAaXRlbSBLZXktVHlwZTogQHZhcnthbGdvfQpTdGFydHMgYSBuZXcgcGFy
+YW1ldGVyIGJsb2NrIGJ5IGdpdmluZyB0aGUgdHlwZSBvZiB0aGUgcHJpbWFyeQpr
+ZXkuIFRoZSBhbGdvcml0aG0gbXVzdCBiZSBjYXBhYmxlIG9mIHNpZ25pbmcuICBU
+aGlzIGlzIGEgcmVxdWlyZWQKcGFyYW1ldGVyLiAgQHZhcnthbGdvfSBtYXkgZWl0
+aGVyIGJlIGFuIE9wZW5QR1AgYWxnb3JpdGhtIG51bWJlciBvciBhCnN0cmluZyB3
+aXRoIHRoZSBhbGdvcml0aG0gbmFtZS4gIFRoZSBzcGVjaWFsIHZhbHVlIEBzYW1w
+e2RlZmF1bHR9IG1heQpiZSB1c2VkIGZvciBAdmFye2FsZ299IHRvIGNyZWF0ZSB0
+aGUgZGVmYXVsdCBrZXkgdHlwZTsgaW4gdGhpcyBjYXNlIGEKQHNhbXB7S2V5LVVz
+YWdlfSBzaGFsbCBub3QgYmUgZ2l2ZW4gYW5kIEBzYW1we2RlZmF1bHR9IGFsc28g
+YmUgdXNlZApmb3IgQHNhbXB7U3Via2V5LVR5cGV9LgoKQGl0ZW0gS2V5LUxlbmd0
+aDogQHZhcntuYml0c30KVGhlIHJlcXVlc3RlZCBsZW5ndGggb2YgdGhlIGdlbmVy
+YXRlZCBrZXkgaW4gYml0cy4gIFRoZSBkZWZhdWx0IGlzCnJldHVybmVkIGJ5IHJ1
+bm5pbmcgdGhlIGNvbW1hbmQgQHNhbXB7Z3BnMiAtLWdwZ2NvbmYtbGlzdH0uCgpA
+aXRlbSBLZXktR3JpcDogQHZhcntoZXhzdHJpbmd9ClRoaXMgaXMgb3B0aW9uYWwg
+YW5kIHVzZWQgdG8gZ2VuZXJhdGUgYSBDU1Igb3IgY2VydGlmaWNhdGUgZm9yIGFu
+CmFscmVhZHkgZXhpc3Rpbmcga2V5LiAgS2V5LUxlbmd0aCB3aWxsIGJlIGlnbm9y
+ZWQgd2hlbiBnaXZlbi4KCkBpdGVtIEtleS1Vc2FnZTogQHZhcnt1c2FnZS1saXN0
+fQpTcGFjZSBvciBjb21tYSBkZWxpbWl0ZWQgbGlzdCBvZiBrZXkgdXNhZ2VzLiAg
+QWxsb3dlZCB2YWx1ZXMgYXJlCkBzYW1we2VuY3J5cHR9LCBAc2FtcHtzaWdufSwg
+YW5kIEBzYW1we2F1dGh9LiAgVGhpcyBpcyB1c2VkIHRvCmdlbmVyYXRlIHRoZSBr
+ZXkgZmxhZ3MuICBQbGVhc2UgbWFrZSBzdXJlIHRoYXQgdGhlIGFsZ29yaXRobSBp
+cwpjYXBhYmxlIG9mIHRoaXMgdXNhZ2UuICBOb3RlIHRoYXQgT3BlblBHUCByZXF1
+aXJlcyB0aGF0IGFsbCBwcmltYXJ5CmtleXMgYXJlIGNhcGFibGUgb2YgY2VydGlm
+aWNhdGlvbiwgc28gbm8gbWF0dGVyIHdoYXQgdXNhZ2UgaXMgZ2l2ZW4KaGVyZSwg
+dGhlIEBzYW1we2NlcnR9IGZsYWcgd2lsbCBiZSBvbi4gIElmIG5vIEBzYW1we0tl
+eS1Vc2FnZX0gaXMKc3BlY2lmaWVkIGFuZCB0aGUgQHNhbXB7S2V5LVR5cGV9IGlz
+IG5vdCBAc2FtcHtkZWZhdWx0fSwgYWxsIGFsbG93ZWQKdXNhZ2VzIGZvciB0aGF0
+IHBhcnRpY3VsYXIgYWxnb3JpdGhtIGFyZSB1c2VkOyBpZiBpdCBpcyBub3QgZ2l2
+ZW4gYnV0CkBzYW1we2RlZmF1bHR9IGlzIHVzZWQgdGhlIHVzYWdlIHdpbGwgYmUg
+QHNhbXB7c2lnbn0uCgpAaXRlbSBTdWJrZXktVHlwZTogQHZhcnthbGdvfQpUaGlz
+IGdlbmVyYXRlcyBhIHNlY29uZGFyeSBrZXkgKHN1YmtleSkuICBDdXJyZW50bHkg
+b25seSBvbmUgc3Via2V5CmNhbiBiZSBoYW5kbGVkLiAgU2VlIGFsc28gQHNhbXB7
+S2V5LVR5cGV9IGFib3ZlLgoKQGl0ZW0gU3Via2V5LUxlbmd0aDogQHZhcntuYml0
+c30KTGVuZ3RoIG9mIHRoZSBzZWNvbmRhcnkga2V5IChzdWJrZXkpIGluIGJpdHMu
+ICBUaGUgZGVmYXVsdCBpcyByZXR1cm5lZApieSBydW5uaW5nIHRoZSBjb21tYW5k
+IEBzYW1we2dwZzIgLS1ncGdjb25mLWxpc3R9Ii4KCkBpdGVtIFN1YmtleS1Vc2Fn
+ZTogQHZhcnt1c2FnZS1saXN0fQpLZXkgdXNhZ2UgbGlzdHMgZm9yIGEgc3Via2V5
+OyBzaW1pbGFyIHRvIEBzYW1we0tleS1Vc2FnZX0uCgpAaXRlbSBQYXNzcGhyYXNl
+OiBAdmFye3N0cmluZ30KSWYgeW91IHdhbnQgdG8gc3BlY2lmeSBhIHBhc3NwaHJh
+c2UgZm9yIHRoZSBzZWNyZXQga2V5LCBlbnRlciBpdCBoZXJlLgpEZWZhdWx0IGlz
+IHRvIHVzZSB0aGUgUGluZW50cnkgZGlhbG9nIHRvIGFzayBmb3IgYSBwYXNzcGhy
+YXNlLgoKQGl0ZW0gTmFtZS1SZWFsOiBAdmFye25hbWV9CkBpdGVteCBOYW1lLUNv
+bW1lbnQ6IEB2YXJ7Y29tbWVudH0KQGl0ZW14IE5hbWUtRW1haWw6IEB2YXJ7ZW1h
+aWx9ClRoZSB0aHJlZSBwYXJ0cyBvZiBhIHVzZXIgbmFtZS4gIFJlbWVtYmVyIHRv
+IHVzZSBVVEYtOCBlbmNvZGluZyBoZXJlLgpJZiB5b3UgZG9uJ3QgZ2l2ZSBhbnkg
+b2YgdGhlbSwgbm8gdXNlciBJRCBpcyBjcmVhdGVkLgoKQGl0ZW0gRXhwaXJlLURh
+dGU6IEB2YXJ7aXNvLWRhdGV9fChAdmFye251bWJlcn1bZHx3fG18eV0pClNldCB0
+aGUgZXhwaXJhdGlvbiBkYXRlIGZvciB0aGUga2V5IChhbmQgdGhlIHN1YmtleSku
+ICBJdCBtYXkgZWl0aGVyCmJlIGVudGVyZWQgaW4gSVNPIGRhdGUgZm9ybWF0IChl
+LmcuICIyMDAwMDgxNVQxNDUwMTIiKSBvciBhcyBudW1iZXIgb2YKZGF5cywgd2Vl
+a3MsIG1vbnRoIG9yIHllYXJzIGFmdGVyIHRoZSBjcmVhdGlvbiBkYXRlLiAgVGhl
+IHNwZWNpYWwKbm90YXRpb24gInNlY29uZHM9TiIgaXMgYWxzbyBhbGxvd2VkIHRv
+IHNwZWNpZnkgYSBudW1iZXIgb2Ygc2Vjb25kcwpzaW5jZSBjcmVhdGlvbi4gIFdp
+dGhvdXQgYSBsZXR0ZXIgZGF5cyBhcmUgYXNzdW1lZC4gIE5vdGUgdGhhdCB0aGVy
+ZQppcyBubyBjaGVjayBkb25lIG9uIHRoZSBvdmVyZmxvdyBvZiB0aGUgdHlwZSB1
+c2VkIGJ5IE9wZW5QR1AgZm9yCnRpbWVzdGFtcHMuICBUaHVzIHlvdSBiZXR0ZXIg
+bWFrZSBzdXJlIHRoYXQgdGhlIGdpdmVuIHZhbHVlIG1ha2UKc2Vuc2UuICBBbHRo
+b3VnaCBPcGVuUEdQIHdvcmtzIHdpdGggdGltZSBpbnRlcnZhbHMsIEdudVBHIHVz
+ZXMgYW4KYWJzb2x1dGUgdmFsdWUgaW50ZXJuYWxseSBhbmQgdGh1cyB0aGUgbGFz
+dCB5ZWFyIHdlIGNhbiByZXByZXNlbnQgaXMKMjEwNS4KCkBpdGVtICBDcmVhdGlv
+bi1EYXRlOiBAdmFye2lzby1kYXRlfQpTZXQgdGhlIGNyZWF0aW9uIGRhdGUgb2Yg
+dGhlIGtleSBhcyBzdG9yZWQgaW4gdGhlIGtleSBpbmZvcm1hdGlvbiBhbmQKd2hp
+Y2ggaXMgYWxzbyBwYXJ0IG9mIHRoZSBmaW5nZXJwcmludCBjYWxjdWxhdGlvbi4g
+IEVpdGhlciBhIGRhdGUgbGlrZQoiMTk4Ni0wNC0yNiIgb3IgYSBmdWxsIHRpbWVz
+dGFtcCBsaWtlICIxOTg2MDQyNlQwNDI2NDAiIG1heSBiZSB1c2VkLgpUaGUgdGlt
+ZSBpcyBjb25zaWRlcmVkIHRvIGJlIFVUQy4gIFRoZSBzcGVjaWFsIG5vdGF0aW9u
+ICJzZWNvbmRzPU4iCm1heSBiZSB1c2VkIHRvIGRpcmVjdGx5IHNwZWNpZnkgYSB0
+aGUgbnVtYmVyIG9mIHNlY29uZHMgc2luY2UgRXBvY2gKKFVuaXggdGltZSkuICBJ
+ZiBpdCBpcyBub3QgZ2l2ZW4gdGhlIGN1cnJlbnQgdGltZSBpcyB1c2VkLgoKQGl0
+ZW0gUHJlZmVyZW5jZXM6IEB2YXJ7c3RyaW5nfQpTZXQgdGhlIGNpcGhlciwgaGFz
+aCwgYW5kIGNvbXByZXNzaW9uIHByZWZlcmVuY2UgdmFsdWVzIGZvciB0aGlzIGtl
+eS4KVGhpcyBleHBlY3RzIHRoZSBzYW1lIHR5cGUgb2Ygc3RyaW5nIGFzIHRoZSBz
+dWItY29tbWFuZCBAc2FtcHtzZXRwcmVmfQppbiB0aGUgQG9wdGlvbnstLWVkaXQt
+a2V5fSBtZW51LgoKQGl0ZW0gIFJldm9rZXI6IEB2YXJ7YWxnb306QHZhcntmcHJ9
+IFtzZW5zaXRpdmVdCkFkZCBhIGRlc2lnbmF0ZWQgcmV2b2tlciB0byB0aGUgZ2Vu
+ZXJhdGVkIGtleS4gIEFsZ28gaXMgdGhlIHB1YmxpYyBrZXkKYWxnb3JpdGhtIG9m
+IHRoZSBkZXNpZ25hdGVkIHJldm9rZXIgKGkuZS4gUlNBPTEsIERTQT0xNywgZXRj
+LikKQHZhcntmcHJ9IGlzIHRoZSBmaW5nZXJwcmludCBvZiB0aGUgZGVzaWduYXRl
+ZCByZXZva2VyLiAgVGhlIG9wdGlvbmFsCkBzYW1we3NlbnNpdGl2ZX0gZmxhZyBt
+YXJrcyB0aGUgZGVzaWduYXRlZCByZXZva2VyIGFzIHNlbnNpdGl2ZQppbmZvcm1h
+dGlvbi4gIE9ubHkgdjQga2V5cyBtYXkgYmUgZGVzaWduYXRlZCByZXZva2Vycy4K
+CkBpdGVtIEtleXNlcnZlcjogQHZhcntzdHJpbmd9ClRoaXMgaXMgYW4gb3B0aW9u
+YWwgcGFyYW1ldGVyIHRoYXQgc3BlY2lmaWVzIHRoZSBwcmVmZXJyZWQga2V5c2Vy
+dmVyClVSTCBmb3IgdGhlIGtleS4KCkBpdGVtIEhhbmRsZTogQHZhcntzdHJpbmd9
+ClRoaXMgaXMgYW4gb3B0aW9uYWwgcGFyYW1ldGVyIG9ubHkgdXNlZCB3aXRoIHRo
+ZSBzdGF0dXMgbGluZXMKS0VZX0NSRUFURUQgYW5kIEtFWV9OT1RfQ1JFQVRFRC4g
+IEB2YXJ7c3RyaW5nfSBtYXkgYmUgdXAgdG8gMTAwCmNoYXJhY3RlcnMgYW5kIHNo
+b3VsZCBub3QgY29udGFpbiBzcGFjZXMuICBJdCBpcyB1c2VmdWwgZm9yIGJhdGNo
+IGtleQpnZW5lcmF0aW9uIHRvIGFzc29jaWF0ZSBhIGtleSBwYXJhbWV0ZXIgYmxv
+Y2sgd2l0aCBhIHN0YXR1cyBsaW5lLgoKQGVuZCB0YWJsZQoKQG5vaW5kZW50Ckhl
+cmUgaXMgYW4gZXhhbXBsZSBvbiBob3cgdG8gY3JlYXRlIGEga2V5OgpAc21hbGxl
+eGFtcGxlCiQgY2F0ID5mb28gPDxFT0YKICAgICAlZWNobyBHZW5lcmF0aW5nIGEg
+YmFzaWMgT3BlblBHUCBrZXkKICAgICBLZXktVHlwZTogRFNBCiAgICAgS2V5LUxl
+bmd0aDogMTAyNAogICAgIFN1YmtleS1UeXBlOiBFTEctRQogICAgIFN1YmtleS1M
+ZW5ndGg6IDEwMjQKICAgICBOYW1lLVJlYWw6IEpvZSBUZXN0ZXIKICAgICBOYW1l
+LUNvbW1lbnQ6IHdpdGggc3R1cGlkIHBhc3NwaHJhc2UKICAgICBOYW1lLUVtYWls
+OiBqb2VAQGZvby5iYXIKICAgICBFeHBpcmUtRGF0ZTogMAogICAgIFBhc3NwaHJh
+c2U6IGFiYwogICAgICVwdWJyaW5nIGZvby5wdWIKICAgICAlc2VjcmluZyBmb28u
+c2VjCiAgICAgIyBEbyBhIGNvbW1pdCBoZXJlLCBzbyB0aGF0IHdlIGNhbiBsYXRl
+ciBwcmludCAiZG9uZSIgOi0pCiAgICAgJWNvbW1pdAogICAgICVlY2hvIGRvbmUK
+RU9GCiQgZ3BnMiAtLWJhdGNoIC0tZ2VuLWtleSBmb28KIFsuLi5dCiQgZ3BnMiAt
+LW5vLWRlZmF1bHQta2V5cmluZyAtLXNlY3JldC1rZXlyaW5nIC4vZm9vLnNlYyBc
+CiAgICAgICAtLWtleXJpbmcgLi9mb28ucHViIC0tbGlzdC1zZWNyZXQta2V5cwov
+aG9tZS93ay93b3JrL2dudXBnLXN0YWJsZS9zY3JhdGNoL2Zvby5zZWMKLS0tLS0t
+LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCnNlYyAgMTAyNEQv
+OTE1QTg3OEQgMjAwMC0wMy0wOSBKb2UgVGVzdGVyICh3aXRoIHN0dXBpZCBwYXNz
+cGhyYXNlKSA8am9lQEBmb28uYmFyPgpzc2IgIDEwMjRnLzhGNzBFMkMwIDIwMDAt
+MDMtMDkKQGVuZCBzbWFsbGV4YW1wbGUKCgpAbm9pbmRlbnQKSWYgeW91IHdhbnQg
+dG8gY3JlYXRlIGEga2V5IHdpdGggdGhlIGRlZmF1bHQgYWxnb3JpdGhtcyB5b3Ug
+d291bGQgdXNlCnRoZXNlIHBhcmFtZXRlcnM6CkBzbWFsbGV4YW1wbGUKICAgICAl
+ZWNobyBHZW5lcmF0aW5nIGEgZGVmYXVsdCBrZXkKICAgICBLZXktVHlwZTogZGVm
+YXVsdAogICAgIFN1YmtleS1UeXBlOiBkZWZhdWx0CiAgICAgTmFtZS1SZWFsOiBK
+b2UgVGVzdGVyCiAgICAgTmFtZS1Db21tZW50OiB3aXRoIHN0dXBpZCBwYXNzcGhy
+YXNlCiAgICAgTmFtZS1FbWFpbDogam9lQEBmb28uYmFyCiAgICAgRXhwaXJlLURh
+dGU6IDAKICAgICBQYXNzcGhyYXNlOiBhYmMKICAgICAlcHVicmluZyBmb28ucHVi
+CiAgICAgJXNlY3JpbmcgZm9vLnNlYwogICAgICMgRG8gYSBjb21taXQgaGVyZSwg
+c28gdGhhdCB3ZSBjYW4gbGF0ZXIgcHJpbnQgImRvbmUiIDotKQogICAgICVjb21t
+aXQKICAgICAlZWNobyBkb25lCkBlbmQgc21hbGxleGFtcGxlCgoKCgpAbWFuc2Vj
+dCBzZWUgYWxzbwpAaWZzZXQgaXNtYW4KQGNvbW1hbmR7Z3Bndn0oMSksCkBjb21t
+YW5ke2dwZ3NtfSgxKSwKQGNvbW1hbmR7Z3BnLWFnZW50fSgxKQpAZW5kIGlmc2V0
+CkBpbmNsdWRlIHNlZS1hbHNvLW5vdGUudGV4aQo=
+=jeqE
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/00FE67F28A52A8AA08FFAED20AF832DA916D1985.asc b/tests/openpgp/privkeys/00FE67F28A52A8AA08FFAED20AF832DA916D1985.asc
new file mode 100644
index 0000000..71d9eb9
--- /dev/null
+++ b/tests/openpgp/privkeys/00FE67F28A52A8AA08FFAED20AF832DA916D1985.asc
@@ -0,0 +1,17 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDExOnByaXZhdGUta2V5KDM6cnNhKDE6bjEyOToAqCYxh+c0mGKVkNRLiSe19rSb
+OgLVJcL6dH1EnawO6klyypIbrDom7DNNTlp7TMlwQ+UsKbmT8jwkU08/awg6W9Wq
+5LCABUStYrVcwJJlf3p4lBru0BSRlaKuIslpk5Powfj2lPXX6o1eRHsnxk9FTD+M
+GcWkhfL9HF+Rq8vPcicpKDE6ZTM6AQABKSgxOmQxMjg6NPUmd199hJrT8TOzgIRl
+vkfedZRLziNM3yBO2nvEjMxKH3uJxKHh/VUg/VLo72On/HIyiQeeDVYcuLJGTm7e
+degk/9C85hT5K4VUF9+LXXDX1Vz/jQdZxq+JwUE/AdlAEC9fkFQzc0ftI832mgjR
+OASwMVphqYUQERz00ve+NDUpKDE6cDY1OgDJoHlM5kAfmQ3HQsykH2QoWnxA6mTa
+aiCn4XIPEsrXCiwObiwWBj3I+w2OTWbodzxWldxBsaYyVCM3bKR6eldFKSgxOnE2
+NToA1X6NuSiiTP6lQcAqnoPC37LE6PUeoohF05hVoRotOm+/sIcve7ZrgVBvELEr
+q6ZU8fUeCUQoMc2ztQEHyC+0eykoMTp1NjQ6HOTajn4vJZPXy/q5sNWhQ7pZDHeJ
+clqSismtIwvuCV3wMAQMIUr+OWTlGHOCYa8FnBn7PbE6TevGdDEE8CQcfCkpKQ==
+=AhP7
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/0D6F6AD4C4C803B25470F9104E9F4E6A4CA64255.asc b/tests/openpgp/privkeys/0D6F6AD4C4C803B25470F9104E9F4E6A4CA64255.asc
new file mode 100644
index 0000000..ddf0fb9
--- /dev/null
+++ b/tests/openpgp/privkeys/0D6F6AD4C4C803B25470F9104E9F4E6A4CA64255.asc
@@ -0,0 +1,12 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v1.4.8 (GNU/Linux)
+Comment: Use "gpg --dearmor" for unpacking
+
+KDExOnByaXZhdGUta2V5KDM6ZWxnKDE6cDk3OgD/BWuU2w+pPFZltSIytQ3wyNMV
+HbFSG5PDdx29GCJU9RP+rWXX4jcKmilUHH9e4CSDmwcHzTNzqlmDrnZgVXd0uhNx
+5LuuJ1vmTbewdraFkYJ5OjoB3Eg7LneCII8M/0UpKDE6ZzE6AikoMTp5OTY6Toef
+zlcVKiPuobKfXHDhIUQPTfGic2Az47wkMoYHo9j9ZE7AWaliMdPz4jLyLfqqoU9m
+H8g+vJhyAc7UnAF2Sk5466FDypdPm5F9PTW3cqqIwJM4WgkSlM8J2hxH4YtlKSgx
+OngyOTob6nEVc0W4M+ZyrqMvp26DaKRnuFwcsDLsN11JLykpKQ==
+=Ghie
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/0DD40284FF992CD24DC4AAC367037E066FCEE26A.asc b/tests/openpgp/privkeys/0DD40284FF992CD24DC4AAC367037E066FCEE26A.asc
new file mode 100644
index 0000000..49d4413
--- /dev/null
+++ b/tests/openpgp/privkeys/0DD40284FF992CD24DC4AAC367037E066FCEE26A.asc
@@ -0,0 +1,27 @@
+This is the unprotected private key for
+
+pub ed25519/97965A9A 2014-08-19
+ Key fingerprint = C959 BDBA FA32 A2F8 9A15 3B67 8CFD E121 9796 5A9A
+ Keygrip = 0DD40284FF992CD24DC4AAC367037E066FCEE26A
+uid [ unknown] EdDSA sample key 1 (draft-koch-eddsa-for-openpgp-00)
+
+The human readable version of the armored s-expression below is:
+
+(private-key
+ (ecc
+ (curve Ed25519)
+ (flags eddsa)
+ (q #403F098994BDD916ED4053197934E4A87C80733A1280D62F8010992E43EE3B2406#)
+ (d #1A8B1FF05DED48E18BF50166C664AB023EA70003D78D9E41F5758A91D850F8D2#)
+ )
+ )
+
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDExOnByaXZhdGUta2V5KDM6ZWNjKDU6Y3VydmU3OkVkMjU1MTkpKDU6ZmxhZ3M1
+OmVkZHNhKSgxOnEzMzpAPwmJlL3ZFu1AUxl5NOSofIBzOhKA1i+AEJkuQ+47JAYp
+KDE6ZDMyOhqLH/Bd7Ujhi/UBZsZkqwI+pwAD142eQfV1ipHYUPjSKSkp
+=SS8V
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/13FDB8809B17C5547779F9D205C45F47CE0217CE.asc b/tests/openpgp/privkeys/13FDB8809B17C5547779F9D205C45F47CE0217CE.asc
new file mode 100644
index 0000000..0c15f8c
--- /dev/null
+++ b/tests/openpgp/privkeys/13FDB8809B17C5547779F9D205C45F47CE0217CE.asc
@@ -0,0 +1,17 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v1.4.8 (GNU/Linux)
+Comment: Use "gpg --dearmor" for unpacking
+
+KDExOnByaXZhdGUta2V5KDM6cnNhKDE6bjEyOToAqFJWduzk11/m0Ac/K/mab0kz
+zr3UUor1bkxh4vcxJHOTZF3a9Y6t1WUpwlOXeCNkY98tRYUg6A40wFgkKz/4jdOa
+iDtHW2bOqrvJmJ/wH/5zdmDpthu53JEgXUKP/+j2dfrvYTZYxy2m11DA68QK9iPS
+BmksglFMQE2IJatwEAEpKDE6ZTI6AQEpKDE6ZDEyODoAvKABRIX7dtUOm2y6VyGs
+ESE5D4YI1AhL0EWodt84EPEUvC1o61UuYbAe28JIHwjIKDLgDiedZ6hTBV3K5cI1
+aFHL421hDE0qtD+mVZhcRGnR2RHhr9gX6qX+4P8mV0w1nhdShwUhlFO1GuwQ2/dW
+KwYdXGbDW7P58LIiudGWuSkoMTpwNjU6AMM8WAY5lr1ZdSqr39rNqntLZqoXVO4N
+ibd5Tw3o/3JMVJ/xEqMykrude87nlPCAJMPlX9gjP1B57UmRxN8mGNkpKDE6cTY1
+OgDctZRfAPGvQ4vUwxG4uso9nbCtFlGYZTQgMPHfMFflUyxH9Y0zA8ujyKKYFPYX
+t7Pe6Y+qqu6BG0mPqvIXe3dpKSgxOnU2NDop+y32myNaSakGsQ732PgarqitgefN
+3h9Kec4kS/j85t1esYEbC9XlFluVcIUDaQHdKFpijCl6eC2oFXOkPRwJKSkp
+=nyLM
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/1DF48228FEFF3EC2481B106E0ACA8C465C662CC5.asc b/tests/openpgp/privkeys/1DF48228FEFF3EC2481B106E0ACA8C465C662CC5.asc
new file mode 100644
index 0000000..688b182
--- /dev/null
+++ b/tests/openpgp/privkeys/1DF48228FEFF3EC2481B106E0ACA8C465C662CC5.asc
@@ -0,0 +1,23 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDIxOnByb3RlY3RlZC1wcml2YXRlLWtleSgzOnJzYSgxOm4xMjk6AOnl30hwc47r
+LL9QH6g0TX1BEPdWMV4Ou6+rQOErIMAr1AOlUzpjwJllvQqf2OHnQWaTr9kbNLn7
+XUEUhjkH3uHDYMHMdyAb7YJrk3ECDqnmr34VV/F/H5BH7D6AiFktl1SpUTczPxBx
+vPNlJ4joPmTm+ahfg+zL+4pVu6tIhM0LKSgxOmUzOgEAASkoOTpwcm90ZWN0ZWQx
+NDpvcGVucGdwLW5hdGl2ZSgxOTpvcGVucGdwLXByaXZhdGUta2V5KDc6dmVyc2lv
+bjE6NCkoNDphbGdvMzpSU0EpKDQ6c2tleTE6XzEyOToA6eXfSHBzjussv1AfqDRN
+fUEQ91YxXg67r6tA4SsgwCvUA6VTOmPAmWW9Cp/Y4edBZpOv2Rs0uftdQRSGOQfe
+4cNgwcx3IBvtgmuTcQIOqeavfhVX8X8fkEfsPoCIWS2XVKlRNzM/EHG882UniOg+
+ZOb5qF+D7Mv7ilW7q0iEzQsxOl8zOgEAATE6XzEyODpfHMTxVhkHswZdPZ3B7pLc
+LktR6NDmaKNVyhP1/G2y95+dY+s2QT4eosp+uYWeR0XHCqNla7TDND41qrzyEAtH
+iAF3OoydMK4lb0lqfKORRI4tr017wgMxRBLs82Gk5ehtI7AwSca7WvaoAJwKZp42
+th4MOeykeGRRMagJI420QTE6XzY1OgDzN2Pz0dRD20hHKF6eiqAZYaZhmA7pKWuW
+jHCVXO9s6zGfn0Ds+kTQJltOxU/AULATN/ffXqTtXSiprxNUvwnbMTpfNjU6APYx
+GOABYcWOpJn35eSoisB04QtOgT5OpAl/dLbeaJ+Yh9KtrY6wLf/mX03FgE+YbkIf
+TmeB6tDf4RYbXCYyKJExOl82NDo5wagaIbek0F5TRtmqdVk1weEk/0XXdyG/mNIA
+4l/qt/LHcduBN46qHYEKnKhyDMCBDwlSRf455FG8Oi1x+JMYKSg0OmNzdW01OjQx
+MDUyKSgxMDpwcm90ZWN0aW9uNDpub25lKSkpKSk=
+=hX0p
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/1E28F20E41B54C2D1234D896096495FF57E08D18.asc b/tests/openpgp/privkeys/1E28F20E41B54C2D1234D896096495FF57E08D18.asc
new file mode 100644
index 0000000..d0b621a
--- /dev/null
+++ b/tests/openpgp/privkeys/1E28F20E41B54C2D1234D896096495FF57E08D18.asc
@@ -0,0 +1,9 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDExOnByaXZhdGUta2V5KDM6ZWNjKDU6Y3VydmU3OkVkMjU1MTkpKDU6ZmxhZ3M1
+OmVkZHNhKSgxOnEzMzpAZ8zkuQDL9x7rcvvoo6s3iEF1j88Dknd9nZhLnTEoBRkp
+KDE6ZDMyOnicJkwzhZjYg5Fd8zqmEsZLPdGwe+z+8DU6lq6zj5HcKSkp
+=ZStX
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/2BC997C0B8691D41D29A4EC81CCBCF08454E4961.asc b/tests/openpgp/privkeys/2BC997C0B8691D41D29A4EC81CCBCF08454E4961.asc
new file mode 100644
index 0000000..13dcd1f
--- /dev/null
+++ b/tests/openpgp/privkeys/2BC997C0B8691D41D29A4EC81CCBCF08454E4961.asc
@@ -0,0 +1,31 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDIxOnByb3RlY3RlZC1wcml2YXRlLWtleSgzOnJzYSgxOm4yNTc6ALWn703ukwPA
+klb9+e/m8qGu/XewzQ5fnciZy+YA71aO1L0vg5idBqmWWhUZ1H2jMLpSmHGTsWvw
+v7OpIgsPcyIqmlJ/hXNFxYI/xS8Y9AzFlASs+DqmMOjBghE5crakHjS6JxtkBNK6
+efB3teA5WlD7oVJwhYMsUtkH8/OJq0Lml3sZaca3vDvm0CnEDlqr0pog6RiDxAmO
+gUO04ZcjaGVz9sb+U+coIe/qG1kJZFGdSpuV1BS79nyjMnmMfNt2uB0w9v1hnGrv
+MU7q+OaaP/ii8+tI01WOGn+KQsJp89PwgcnA8y57Up3zN6pDl9WF80uJL/J3FIe8
+RuaE4VBv76spKDE6ZTM6AQABKSg5OnByb3RlY3RlZDI1Om9wZW5wZ3AtczJrMy1z
+aGExLWFlcy1jYmMoKDQ6c2hhMTg6fMHJiYfEZhM4OjE5NzM3NjAwKTE2OuNRxs9I
+ktHtlDMTy6rWZJgpNzM2OlWwk5Xhn92HLSgS6iqiDLYg3NLreSQrnI4i2ujY97BD
+R62o3Li+mu2wO8zFy+zErpMAg1Xn8Cy5III9jQYznUfUCa4UbThAz4XnSTHkP2Ta
+/YunBqAnetFmj+HIeSpFcsUEY/MF9bKNuiEtA2Te0J1X6BYUMY163TxfkLZDTG51
+tyuEqn8n2B6fBu/Vjysyq95ohrrkvIkwIs3p1UOa4qgn+wbr4br8Bu6mf0+ClXoj
+nPCim1aQMrzZHyWYXgqnFjRnHW36lHpdWGqav7vV3+qbjzlVMldOGx24PH1bAYnS
+BD5eeMletc524qYBSxSIyItuReieymNNYAoF6Wf7ayDzDzf2pGrY55wIt6vH2J4D
+24M1ydvS99ibu80A8O/K7WuYHTcrzgPPmp6/aA3q8kxGFrHrAZ1r54yHPKbYnNWE
+v0BxNe0poaMZJKDQIoJT0mGEmlpS4lr/K58QyECIDN1nOVyKL7ixxsqjJI3G0ZY9
+vpOpXHzFIToA8U+/82e/qNUA7wkQMOhG2lF9AxyT5eEOEhCW8J7QZM+FO6ocplgH
+ZxwHa0ymv8Tj4yOVFNSo/ENJym1HGiyvjgnQS2MSZ5kIyVNuGI8AWPsWQJ6B/04p
+LE8apX775kVhvIX+DNU4Bnxnb7KtG2HovT9NxQIzIYcANC/rOKdOq2j5vS4XqHsB
+O66pV0JLa8TPD5iKDIzS2ONBxyKi2HqRg+xkEIpNBhvrQgGs2FzoRvivbjBOgwjp
+hRkX1dkF4axKWEPRuUhvlA7f/TzbHFtjbWyd5fm57j3BgsVj/EcSrGtpl5JQd4k7
+etSIWvtWWySZJPDXz7CW9Wh7W0ZXA76tmniLDeYl8lnMIYa6ylttTnuiW4hh3naH
+JFtWytL1ivCeo8iy5wGQ2X3Jp1C+Y4+lgR4pPE8w04y5Rzo8Jo3VSMWbeovn8djM
+qfXy6yH7H6qHYCO31IJxFfz89EuCE0EGrYUzDFr5KpUpKDEyOnByb3RlY3RlZC1h
+dDE1OjIwMTQxMTAzVDE3Mjk0MikpKQ==
+=jzZd
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/343D8AF79796EE107D645A2787A9D9252F924E6F.asc b/tests/openpgp/privkeys/343D8AF79796EE107D645A2787A9D9252F924E6F.asc
new file mode 100644
index 0000000..c674b65
--- /dev/null
+++ b/tests/openpgp/privkeys/343D8AF79796EE107D645A2787A9D9252F924E6F.asc
@@ -0,0 +1,17 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v1.4.8 (GNU/Linux)
+Comment: Use "gpg --dearmor" for unpacking
+
+KDExOnByaXZhdGUta2V5KDM6ZHNhKDE6cDEyOToArHGqWD0rP0Nn/c3nYELTD4m1
+gqR7f2+l1ZUMdHcweYwn/fVjaJKmbR+9GzeHWP398FWYs5mCU1DIfrZLF0nJnAJ6
+WRnN9TL+oub1BqqLvCmDSngRuZZ2gUX8DVmD8xTsPnDnG74QDUnvtnpDIAs32sg5
+dnusstrriXD8xXgt0g8pKDE6cTIxOgC449htJbbp5rkJHvBDs4YxEIkk5ykoMTpn
+MTI4Ol+ITxpSMOT5R67Bu4XWoYU7nVeYURpb6LJ8LK2CV7ygECwFdRFdukiGFB+a
+TP8nF6xtuXalaBuerkKp4QXVKqOIkp7MWN2TAOOg9eERHPT//whryf49meNYMPLv
+KAe60udHY76Glm+Zso+24WnEwXX2od1PHVV3CItWRb7YmhgGKSgxOnkxMjg6AgXt
+40h2lpiIHTjbu6fiCBzbr5j2eQX3cNoydkRphJ66bqD+DsPW/Ag0WBCQxgRaLgMr
+db64fQT+fyjbTBLbC8ytt5hpCbm/q5x3TTXDAUNjoB3CnA/tQItBy7qqq/A0d3FZ
+grr6AixK58uZ4wauy8LRZCph67UZ8akcgwJkmVkpKDE6eDIwOn/Y1rjZASGMK9IG
+b1y/ZDKT0zkTKSkp
+=muRa
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/3C9D5ECA70130C2DBB1FC6AC0076BEEEC197716F.asc b/tests/openpgp/privkeys/3C9D5ECA70130C2DBB1FC6AC0076BEEEC197716F.asc
new file mode 100644
index 0000000..9a6e102
--- /dev/null
+++ b/tests/openpgp/privkeys/3C9D5ECA70130C2DBB1FC6AC0076BEEEC197716F.asc
@@ -0,0 +1,31 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDIxOnByb3RlY3RlZC1wcml2YXRlLWtleSgzOnJzYSgxOm4yNTc6AK8HhE8MmR/i
+QdHw5kcWa8Lm7henF1KdhF3Z5iDNeurFrDQsg/RFHJbaMyVCzCP/Jc4ayub2FzeS
+fJdKXrpMPAdaGjlbGLdY08Fc49E+7M79YQXgyGXhTm3kZa8bw+TfYnLJC6snxefG
+5YQqEpvV/mfvfQd6XXxDcn/u56YDJ5Lo7xRXmnd4Ifj6T1lF2KDQtDAB1vlpnuxE
+QfnAI8C8UpsxOWC1tSuQ5HIoFnwqAEfEiHH+P2YuHG6m4oyUfT7c11rHf8S01R9Q
+JQCr11Dn9WMAI/IHe67BsrbIAxG+9yeBhIkEShBBxdNqIt2FnE+sTmQHv+uiY4ya
+3ch63dvZ53MpKDE6ZTM6AQABKSg5OnByb3RlY3RlZDI1Om9wZW5wZ3AtczJrMy1z
+aGExLWFlcy1jYmMoKDQ6c2hhMTg6+Nvda1z6F404OjE5NzM3NjAwKTE2Og6NQq99
+p1NyYxcYgwRiATApNzIwOgzqYGEJNhmx149fV84cgLNbmIifZ48o+oywHbwdju0c
+oNmaBHv+Xkm/U5PG/CPYINJbFIewrxuNpGbW69VMfOi5nwcvIE2LouuRd4Ih7cYq
+ub9fjqIH9tO4AA4kkSA932AfJseLTZMcSqvSmyIE4GU6psDjQHuXur4ywKYX0iPi
+11hlhFtiARw4S3ToidPukg+SiEJV6Sec77BmQ2NG55FEB3GiM8m5LOMSPq+ZfxI9
+RmldLuyC5TfGWRgraR+3SU00gYkbAOjwlblHloQzoHquCpumujGvSxYolDsW32HO
+Eojy0k5iezdwbnpBmdWJbnI+qAQQ2wjmEFPKVPnOF4y1Nki+sRXrgFXGbgHwHbRN
+yMgRgMVeYycHhhEz5N+VwQ5yKE3hvIbD0dznD6Z8QAb4PXem929eJDz3FrR8gasN
+2udqDyHkczK3y5oJs4k82Fnmn3Rjfgddyo04SSf/1Gwg31y33Xh7dkdtU+NOt9s9
+wCu+nJhdbh/IH8fXPax2HuWY7q0EPlZQldbeBta4r+RWvNFFDAG8DK5uBHQqtKoV
+vV71ffPm30s4ysaSF4mqF3eIYLltPYNenvsYKpT/cn/3WvbLsKqMIOGytz3P8fQb
+49ZDGDyzT1rQDuJ2oDk7N+epZu+lna/nRo7UBEo+Tf7CkcTKQ97wY8tqqLUdclJr
+KJsIIutg8WgIx09Xvip1gfOAZV4s9V6aMejT32CBLSEmC86t/Tu+3HrstX2E3F8+
+Sc0gB5B62/PMSzCI3lgkjMRp6yCzm0cZkHSDHOSLpoEvSehV0Gv33DFBPNog8XVE
+A4H404JRMBHI5mKpYcYKv/o8ZpQgDGORMZYf5W9/LMF06QZGz36kPVyIwL2j8oCr
+0T0kp/ik8WZSV+BkwKON2fPkROQ7c7ZM+S/xcrpKEe40/dWtTZUABGhCL7IXwlqm
+u2nGS/Cfjmq3TRuRJAZFZykoMTI6cHJvdGVjdGVkLWF0MTU6MjAxNDExMDNUMTcy
+OTQxKSkp
+=04As
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/449E644892C951A37525654730DD32C202079926.asc b/tests/openpgp/privkeys/449E644892C951A37525654730DD32C202079926.asc
new file mode 100644
index 0000000..1a6a0b6
--- /dev/null
+++ b/tests/openpgp/privkeys/449E644892C951A37525654730DD32C202079926.asc
@@ -0,0 +1,10 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDExOnByaXZhdGUta2V5KDM6ZWNjKDU6Y3VydmUxMDpOSVNUIFAtMjU2KSgxOnE2
+NToEOx/Lj6ZzYdOMdprseVCR/dwZaYPeInquOlapE22Udwppy4tQqj2jXDYH8d0Z
+5uRvT/FD5lpcW+Cv+BAoo2auuykoMTpkMzI6Xka+GGkZ6tp+azZo+LPj0inV0GnO
+vact0wafLNZvlQQpKSk=
+=Rgp0
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/4DF9172D6FF428C97A0E9AA96F03E8BCE3B2F188.asc b/tests/openpgp/privkeys/4DF9172D6FF428C97A0E9AA96F03E8BCE3B2F188.asc
new file mode 100644
index 0000000..0524739
--- /dev/null
+++ b/tests/openpgp/privkeys/4DF9172D6FF428C97A0E9AA96F03E8BCE3B2F188.asc
@@ -0,0 +1,31 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDIxOnByb3RlY3RlZC1wcml2YXRlLWtleSgzOnJzYSgxOm4yNTc6AMwChvrQ9TUc
+PtBbfK0UWOt2GZrzq7I0ZhcjfoxGD4UXxKNBxHcyb2cQYTh5tF4XqIv9d2Sys1c4
+fU2Rr6lnPDc6VpSLKoHZj76jWkcWVf80+MXFNVp/YqErQBMu/AkA/Cwk3hEgjqQI
+ZOo9awfBATJqGmW9y3Ct1IV8oM6SUOjYQ8CcIa2jpSNNq9rhXQjzTYUZHK4ayTmj
+mPvuqSxWahUsOZClA3GHpLZkFe9k2UJuVIUfhwYD4CyIR1nqlFfj87p/UEPs1264
+/RpBagz4G74BiLhiHQss8NXm1zWiRZ1xPyJIkrDm42JRQ+6gGf1qvk2tyS3Le4W+
+7sg3r08UExMpKDE6ZTM6AQABKSg5OnByb3RlY3RlZDI1Om9wZW5wZ3AtczJrMy1z
+aGExLWFlcy1jYmMoKDQ6c2hhMTg6xlhuUgeZDb84OjE5NzM3NjAwKTE2OilEwfz2
+SNwgLhCK76qARHgpNzIwOqgwKI52Qj5ABmkzDaJ3srvp4C6GnCFvosWjaNBZkLaX
+z2cGEh75T8Klm/RR8tXhXxHcl/b+UErb0CDRy6nQvMhU6LX+0hfk6t3M+wE+Wz/Q
+/uPoT5cdgWRUKBjCzSgH3DKwjBM8z8L14UCsZt17vEDVwE3jvAIo7DmvCjAKt4tP
+jyyBUMl8kn7HBAJkIthCnNZ3Egj1o5NqYVc6Dbh82x01lPh50EkNUOi2MANRxkCG
+Ycg8zeB7uaMwM7Hu+wtev+QMve3aoRVRGHIEbwzj6wl/OwmSROWmQxmLebs20dMD
+sdhaUkfGV2EFXSzgsK8q3zrWN7mkr/h5zs63kvsQnbsOU3ym+/OPgCOUSBm87Ggu
+GyUoIblgyzJHxNHN0x0RoFue3JE4CCZvsj+Cn9auwgniBCTMBHhanLm4+y4jMAdU
+CEdHV4m55FOG1i5AyNr9m8U3/SPzlHdPJ+9P/8hEJhcB6tbX7I43K8Wl+5I9yJI4
+p6gI7VQhLCjmpUihsnRdmFGfxneDxNNIlzDwPOoV0thfOoju15ofxNdDHCzWhiin
+2WVhQ60iHLT1Pfgk1htGs73wIFDsmHdJphmAscCq+uPDeDu34GPZi+DGQIndIlWw
+2Dx0QjvtV5DYYHL4AYKbvCrMhTF+2ECZB1WuwTRV3AaOS27GnaneWK6KURrAE8p+
+LSIvFya6g6tbjScflrLNBm+8n7/Iyq526IiwgxQC8g6t79AxxKBSarjw2RhQRi5Q
+PJymKlVvp+smFATNLMC+cjEFSP3zf+8a1gQnmSuaSY+UmhG/yakDlEmZzTRH5K4r
+rzgFvQhi4rZMCSBTy2I08IsIzeZhzpsrWmsTCnPIaFZ3VwzzabbLV2pwWda4hW0M
+vXf1SZwL02RujWISEiJ5ufPwm6eFwH1dNRvxSTN34cw53/cFyiuuETDx2/XIp7Ec
+ODuPCvJvsVjRUBQ6tdxkLSkoMTI6cHJvdGVjdGVkLWF0MTU6MjAxNDExMDRUMDg0
+MzIzKSkp
+=opty
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/50B2D4FA4122C212611048BC5FC31BD44393626E.asc b/tests/openpgp/privkeys/50B2D4FA4122C212611048BC5FC31BD44393626E.asc
new file mode 100644
index 0000000..6233524
--- /dev/null
+++ b/tests/openpgp/privkeys/50B2D4FA4122C212611048BC5FC31BD44393626E.asc
@@ -0,0 +1,21 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v1.4.8 (GNU/Linux)
+Comment: Use "gpg --dearmor" for unpacking
+
+KDIxOnByb3RlY3RlZC1wcml2YXRlLWtleSgzOmRzYSgxOnAxMjk6AL8pJ97q5V8O
+ADcGsak0uFXFP/K3BcykEjykR1OJjSNaditv9i7zC0J5n0YC7H9kD+1537ul2Jsd
+d9fk/MN+BRNnCsglrns5SlbAjzvwDNnE2ydW/Ug/q58bIRIowTg9RA7mF4qHABvS
+BDAXACtLe/ih5isSWOEnv2Sm3fX0kQATKSgxOnEyMToA+hTknylYwYGT/PEVQ4Jl
+LPoWmqUpKDE6ZzEyOToAmfUdfU53m3Kgrg4QAzkb7AfPdIGPgUyidk1azUi3Tcko
+egzm6VDYWARaYFUg9MpIOb+NBc9gCnPkOnGmgZhtMJoSjrN8TfYATOhcOYYBkT3R
+eGr/BwQ34lwekfK0AD+f6FhpHexh6BDnaZYxH691330o7RXSMtFxySAEDtnaOUUp
+KDE6eTEyODp8cyy2nYt0QI5Tf+t/d4WBeib2yNWVtZH/j7XpDqHLZDgVAYkazCA6
+ZF7BvLddBEqVAh1X5tqua4AXX9L4SGYb7B0LRV72alhYiWWHez126KjVgwRTUxtE
+J4EnHmYJRReLlXosPIRhXSz7HFAqalPXJ0DvC9kzTQnnjPOylyMPTSkoOTpwcm90
+ZWN0ZWQyNTpvcGVucGdwLXMyazMtc2hhMS1hZXMtY2JjKCg0OnNoYTE4OnBnEA/u
+YyreNzo0OTMzNjMyKTE2OtXuvrOxsl1/bOm+6zBEQZ0pODA6XEPa+d4D7F2jof/+
+sJvtf22PzAgN/qZ93eIKlJaHxQFQeOyLrghCAUyZLIBzR8dlNBG+uWhg7DBJMVnR
+MhH24nqzdivp+SxlMO0XdnkmkBspKDEyOnByb3RlY3RlZC1hdDE1OjIwMTAxMDE0
+VDEyMDgxMSkpKQ==
+=ZfqD
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/58FFE844087634E62440224908BDE44BEA7EB730.asc b/tests/openpgp/privkeys/58FFE844087634E62440224908BDE44BEA7EB730.asc
new file mode 100644
index 0000000..103d043
--- /dev/null
+++ b/tests/openpgp/privkeys/58FFE844087634E62440224908BDE44BEA7EB730.asc
@@ -0,0 +1,31 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDIxOnByb3RlY3RlZC1wcml2YXRlLWtleSgzOnJzYSgxOm4yNTc6AKotlDIKDSEy
+vIjkWDdGHQCzm1ebRtyb15Ljkl17NV4biDAA+2qOrw3QJQ+6CfVpD8XEygXpBEv0
+16VgFuB5MsINHNE94dKAUc0R1uUwZljeINPQ2F/72t3SFiiBBGwY4AHDNn/zi6Rc
+M7JwjJW/pkkqcmvy1kA5kP18XA6wgY8NsyCa+H9ZJm5BK64MSGUEdscWykuHUW3z
+g6Dc8bST6OhlokclRWh9KVK0QRbqnlQeVP/E/Kv4LhnbXNB2GE2Yecah4rva/PNq
+2YZ9CfyuQHwSJQhb1h1MKLi57AAacgAhV6OcR1hM6We1Vh5JDFEj01DsIMC11S1Z
+zHYLXRWAec8pKDE6ZTM6AQABKSg5OnByb3RlY3RlZDI1Om9wZW5wZ3AtczJrMy1z
+aGExLWFlcy1jYmMoKDQ6c2hhMTg6O8dPH/PCXh04OjE5NzM3NjAwKTE2OhEO7X2q
+8iasv3iHvYbCdQcpNzIwOjBesXtjq+5LWL6zU5yqEK5GrykQBIHisxNK+2TA3vBM
+sb/646D5Za60r6rjAShVxIWa9c5rzmS+rITBVodTzAjOn2uj9k1TQNmqsWf/i3zj
+xe6puh6e0IIkAoMcHpRozSOHF1q5YDKfI7wjr8+u+TdROFhEhObQ1CXTnjTCx1aB
+oQG5AvybctPjSCdYxVujXmNjrgngZodiTxsE4OBG/bk2msK6GY+oJKgBCp/5m04Y
+DGDe2w9MDt7UcW0tlo2kHk5cwKPs/ziSu1gfaFqqOzFBdUc+gR5ikbzDF1vJ53W8
+3DwnzCSkuciBX8MeGiAfkR8f0WQsBStMNZewnCsPYeB20Cl8bTAtzs+X7LKzdSI2
+8gSkIV/GD3VwYw80cqn2eF+5cJKtKIV1nOxPRoXgcuWvNTL2nyLggaJDVusy3MKY
+O3yNnadWmA1XT8NMBx+yY1i0pCfmxWK5h/2F2cNbe21MyhlwgkGD8jVZCiW/NeCB
+VdpFHcqZz+rYchLTjs+LSoINKFiwoIpK54pMAuRO+E1y32Zo7XoZqyDkU/ip2iAK
+OaB5LTjl/GI5ISRBcsxbPXOxbNnUat+0p88T4Dj/V2ZJkubAwRIzgOE9p4TgHqlF
+2kkl+4rqqnooDUQ4ViEIUxjq2YIws9wkWAthMMcJVDgRcD8+G6IGAJ3tQlIaW9oA
+OVLsHcXdiFbcEE12m30CMI0uUQSavk+aO0qO1ZQRYtu9EipGWnjWs+0ZqcMaz9rj
+ACv6rvsts6puie3uvL+yzEuzpWC74e50kElF0MLVQropNY50hvXqrnKzoU5ppaNt
+W7q4vrtKZh7QOFt7mcG4oTSIpr0vTwBGl0YbrORviF1KdaW2sPHNfbL7hrTx1HlU
+3BnAM8b0kYz+NEJ1qxNUfymta5iZI21LebJNTWJIiiCBS33J73Cxr92UaafU3VRA
+jZRpavMXHHoesBZ78uDqAikoMTI6cHJvdGVjdGVkLWF0MTU6MjAxNDExMDRUMDg0
+MjM0KSkp
+=zQRC
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/6E6B7ED0BD4425018FFC54F3921D5467A3AE00EB.asc b/tests/openpgp/privkeys/6E6B7ED0BD4425018FFC54F3921D5467A3AE00EB.asc
new file mode 100644
index 0000000..ecabe4d
--- /dev/null
+++ b/tests/openpgp/privkeys/6E6B7ED0BD4425018FFC54F3921D5467A3AE00EB.asc
@@ -0,0 +1,31 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDIxOnByb3RlY3RlZC1wcml2YXRlLWtleSgzOnJzYSgxOm4yNTc6APL1FJVAgVOE
+iOLqgmqCWcCgIfl3FT/pBaLJYLO8NersRuygQ6ArAdNYar/h8MKnOkYCwlISr3fp
+Jtj6cpPrz6IU1K09HYEpVc6n1UbD5r25sDc9Ol8ztg5QPVP+ceA42nzpHAnMAW7E
+9dz5gsM/H6TlicF4qOT3rOfpBqDx1EHOaOS6pdnem7SwSQZ6RFetJotkXqEFfSNV
+lMTLqqysfk5kUW+jn7B4Jlpd7YWtlaLsPXyY1dFwi24VqpIiztOYRoWFObySrpZk
+wuPGkQ5P/Eqi/2+L7VKXNfODRI0NV6GX1FaQ96lIq0Y+z1EWojLwPb9JR2FLGqC+
+4/mm/W7Unf0pKDE6ZTM6AQABKSg5OnByb3RlY3RlZDI1Om9wZW5wZ3AtczJrMy1z
+aGExLWFlcy1jYmMoKDQ6c2hhMTg6vkrGYgB5EO44OjE5NzM3NjAwKTE2OuQHqFdP
++Q1Oz+cCYcb27DIpNzM2OjoNch/oeQ0jhPqg+yQ0z3Qf26SgZEKqsdozUsPbhBfs
+n4zjoOj3goT4DTFl/pCWL6lCMy56Tb2Ra7j/SUeKAqBSSwarsG6mrFktOQntpw34
+QWxaOc0dJEmy5/IqY0uz4vK6y8X0MWPTDPt0kxvi5Z74MQ1uVsC3ZnepSenLpr/W
+F38jEsq3CHO5rXUDrwMLLTqL0zE9bE4mgQkFIrzZ0UFM8iFi7cI+Yyp/esbZHubJ
+MqJD1QVf9TpA8OAVXPj+JEYljsqszvjqWbO5pceTyT3OxS0/t0GXeGkbhgS+42qw
+VOlZQe8r8Zs2MfJcGKwTGxS4HW218YZxZAan0eFOsVan+gKthNRGjvJzyy2w9foV
+OND0EOzkeBFDohjWN8ROkVI2z/DyG2WDoc2H7tiajWHTr31uhNlMXDLynhp+zoRV
+GfWIEsrfQiUcnuPyWP+tTyHoqTlAPOqeosxDsZfosEN/GRxgd3CFT1OBdgjd0YHc
+fB5Dfc8JtVvZwXECz6A2eXCOCUJ7ljRpNp4bxtnRoO9VAydWcgpAq8DjwkgiDqLR
+xYAvjAe6irEKNBKVocGV/zw03JvkqnYW7ChLr7sNfiJReFuiJXmWq1mYerOHo356
+LIaZsN0n7NW0OmQmAQmv2ezC1ZCMyjuIMKcDssTieln6Yi7NmmmRPCkkiWoK2XtC
+PVY6Q0gZ1zUysQ4O/Rcm3Nt+U8JUpeXvry0086f0sk0yEdzB0RbZFyYMWFzwNSW4
+VsYtxqvzPVmYHBO6UihvmPnCuwIpUBVpKjsXN3NiARlPk8uAzR/quOgLxVIX6leq
+1hT9DohrFGxP/O1SQhgD1xZfMRwJGo9J7OYA9JWRvZKguM6bJMYZ7Y+PJWZDfifG
+TuQLPq8eA7B2KXEzNjHt6tyyDmV/SsbEoUPZBmGqD59/4JJiHtRy5HJdEAJXTYul
+FpV6Fx4qVf6IjnH8ax8tmxLenGBomboigTofJFnz51MpKDEyOnByb3RlY3RlZC1h
+dDE1OjIwMTQxMTA0VDA4NDg1NikpKQ==
+=4K7Q
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/76F7E2B35832976B50A27A282D9B87E44577EB66.asc b/tests/openpgp/privkeys/76F7E2B35832976B50A27A282D9B87E44577EB66.asc
new file mode 100644
index 0000000..79699a2
--- /dev/null
+++ b/tests/openpgp/privkeys/76F7E2B35832976B50A27A282D9B87E44577EB66.asc
@@ -0,0 +1,21 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v1.4.8 (GNU/Linux)
+Comment: Use "gpg --dearmor" for unpacking
+
+KDIxOnByb3RlY3RlZC1wcml2YXRlLWtleSgzOmRzYSgxOnAxMjk6ALZlsUNfTCYk
+jzIsNhB0iJl4C4cuZ/IeypdosZQxm1aIC+f+E2ly3BqGbMqbmheKcdS9SQs5DSzy
+s6W7XmeHDhrNzfStM/UuwiSfnM5E2cV2BgLpErKE56Kb/rf7/Ia12dObj2VV9oKr
+CwSYEISRdp5YMar6J7Vvz0nz1Pqf8mq7KSgxOnEyMToAoQkjVeVGG+B/SzJ6+yif
+dHWQVkcpKDE6ZzEyODoVw8i11+Plhxj9mnredV5SqI1hsLGZnPSzz2IcFP0XFDu3
+HtUEG9FxZVFRQYWNCUKTP7cv5DYvmhlhc4oG0PhwFmZFLwPPlSAFZ3jfqfkh4RiM
+i01yqQGE6uOgML5ZWeQqb39Ngqf/ltWlcgNKpwVjMniMV5kfRzoupccZ+XI2oyko
+MTp5MTI4OlVm585daoJeQG/Pg7LdDkVuNBDT/63LysOfw5NqI+LjUXJScSLos76r
+IFLT0WOdmP74+RxFxdb31I3GYQlFjsy40e3nAi8QfaM0Q4n2WzPNkUENu7CyNccr
+fn6U9sYTLr3EI/bqIRp/KwoptFcmETUL62TxKcr4abrayK+Yr/lqKSg5OnByb3Rl
+Y3RlZDI1Om9wZW5wZ3AtczJrMy1zaGExLWFlcy1jYmMoKDQ6c2hhMTg6ndF2xFqT
+19k3OjUyNDI4ODApMTY6QB3EeZz7Zs2uIRmjRj/ocyk4MDoN3zs2+IgNNxe0pZQ9
+XzwAAgAA0MhK4ypYOdDc2fvfvCsjrhQyUW5ZQVVxFmf7hgY6YZzAlldXF9bD9DMC
+JtcJmap6Xk5D7VClxR97yHK+ASkoMTI6cHJvdGVjdGVkLWF0MTU6MjAxMDEwMTRU
+MTU0MzUyKSkp
+=8r3/
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/7E201E28B6FEB2927B321F443205F4724EBE637E.asc b/tests/openpgp/privkeys/7E201E28B6FEB2927B321F443205F4724EBE637E.asc
new file mode 100644
index 0000000..7ec0448
--- /dev/null
+++ b/tests/openpgp/privkeys/7E201E28B6FEB2927B321F443205F4724EBE637E.asc
@@ -0,0 +1,18 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v1.4.8 (GNU/Linux)
+Comment: Use "gpg --dearmor" for unpacking
+
+KDIxOnByb3RlY3RlZC1wcml2YXRlLWtleSgzOmVsZygxOnAxMjk6AOgCS1p47zcd
+ec0UvVC0phewalHUU6f7mulWr0j0ZY1RU0IOP18HAeT7INcwPcUaUvC9KYenXmYb
+vO1i7sNNUCOsKUamwg+oSNMcbM3AwNwxlggTyJS1N6WzIX7MjRLUlUqtbLRhPDGl
+Cltt6yeAjS0pZT646TANaBDiRIgk94ADKSgxOmcxOgUpKDE6eTEyODpGh2X1Sy+4
+Ip/RtMJDPZOY+Y6sWUN7OiM2BkdUmCLOmaOVfgrsEevKdSBBj0oVWN81U02i7jQz
+hhAI3tZMFJmP/hlF7AlS5HSaLj2+t1nHAKKy70QhskINR41CCv9sHAc5gN1WrY5N
+DpeI12GmqsWMPQVPUHsTTe0QsT6XbHzvCykoOTpwcm90ZWN0ZWQyNTpvcGVucGdw
+LXMyazMtc2hhMS1hZXMtY2JjKCg0OnNoYTE4Or78V63MKf6HNzo0OTMzNjMyKTE2
+OkxDOAnTGrRgVCyb5u0UbCYpOTY6tghO175Vpfia/wJGrOUT0hgS3Es/EaEHv+bn
+jYBeErvROJrKtUboxoGox/Qa2xxpFFhFWtR3IX6rjmqS1a5RhwEmYxFb/IzVESuZ
+Kf00wS+lmJuR14ACnuAOfVF6OQP5KSgxMjpwcm90ZWN0ZWQtYXQxNToyMDEwMTAx
+NFQxMjA4MTIpKSk=
+=a0Os
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/8B5ABF3EF9EB8D96B91A0B8C2C4401C91C834C34.asc b/tests/openpgp/privkeys/8B5ABF3EF9EB8D96B91A0B8C2C4401C91C834C34.asc
new file mode 100644
index 0000000..370e862
--- /dev/null
+++ b/tests/openpgp/privkeys/8B5ABF3EF9EB8D96B91A0B8C2C4401C91C834C34.asc
@@ -0,0 +1,14 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v1.4.8 (GNU/Linux)
+Comment: Use "gpg --dearmor" for unpacking
+
+KDExOnByaXZhdGUta2V5KDM6ZWxnKDE6cDEyOToAzNix+drHTYCMxS8NiUZNpVTG
+nWfzMjxCqVyZYt9CEm7A4JcfSbgRUppqKunwreuDmmNGFc1W+lT1oLfvJaDi/oQ/
+oubgIcq0EZ5gOUydaj961PV3ltNmaaUSZsJ6jRxaa0FB1cgx6EVB88gR6JB4mAM4
+KV+Ct/f9QzPv2TMS8qspKDE6ZzE6BikoMTp5MTI4OjdzptnsiJ124yTW5ewhvUVp
+mDGuT9CuA3ggW65bjOhfravX5rfHMCXLPXMNXFgpA012vghVwun/ekkj7/rxapZm
+lE28YpSDj8Pwn/lkqNAjy466My+wUeoCgg7mEg/75is2ogKzx1L52nay7BGmfS41
+5m7BBjWHsiUA6KRtFXt1KSgxOngzMTppFcbO0lgUP4k3sTNfSIfwBCt8YwBTmPk5
+a7hTI4y2KSkp
+=miH9
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/9D7CD8F53F2F14C3E2177D1E9D1D11F39513A4A4.asc b/tests/openpgp/privkeys/9D7CD8F53F2F14C3E2177D1E9D1D11F39513A4A4.asc
new file mode 100644
index 0000000..f237e10
--- /dev/null
+++ b/tests/openpgp/privkeys/9D7CD8F53F2F14C3E2177D1E9D1D11F39513A4A4.asc
@@ -0,0 +1,10 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDExOnByaXZhdGUta2V5KDM6ZWNjKDU6Y3VydmUxMDpOSVNUIFAtMjU2KSgxOnE2
+NToEMIx/SmNEvuSVkX0Xq60JBOTUT4qTr3ywNqUOSaKijgdYKjwkIF+jpD+7TfSW
+vMznIU/Ued6WdRrqtQbi4KVzdCkoMTpkMzM6AIbAgwG04OO3x2tqboQ8eGekVM24
+4oEWVVQjQwNeheokKSkp
+=RxSg
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/A0747D5F9425E6664F4FFBEED20FBCA79FDED2BD.asc b/tests/openpgp/privkeys/A0747D5F9425E6664F4FFBEED20FBCA79FDED2BD.asc
new file mode 100644
index 0000000..616c697
--- /dev/null
+++ b/tests/openpgp/privkeys/A0747D5F9425E6664F4FFBEED20FBCA79FDED2BD.asc
@@ -0,0 +1,20 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v1.4.8 (GNU/Linux)
+Comment: Use "gpg --dearmor" for unpacking
+
+KDIxOnByb3RlY3RlZC1wcml2YXRlLWtleSgzOmVsZygxOnAxMjk6AJyN1x9X9Lsj
+fX2Z8O9s7BzMO9OoOxFtvZw+FA0BuDs0WVYkq1GuZ9/XiO0K30zvtZnlb7NMvBfz
+7xbLeYx+vKzy5xkq18+LE5dU+HKKdRQZKrrwgCsDy8tJRO447QsiLTksCDqPMaE3
+2OCRBF5nKrG5vih7/cmEhf2CuAn+2yM3KSgxOmcxOgcpKDE6eTEyODoZ5eYysaLn
+AwPeqQ9vNvUyrCxUEmrvl4svG7zkkg3ZcgAbDpDQUmnijt3gEBCoAzO3c41TU5wJ
+aUNBEPGPWfKcTlmBEGJWjK50QQuA2diGncxIS5SDs+QVaf434a6/KFVQcCmV7K8/
+T2S8/nuGJ/rIlFL5XovW6A/S9mYEjh2pDykoOTpwcm90ZWN0ZWQyNTpvcGVucGdw
+LXMyazMtc2hhMS1hZXMtY2JjKCg0OnNoYTE4OkuRjUFO6YIJNzo0NjYwMjI0KTE2
+Or7L9Ekww4C0lZz3g61PzJEpMTkyOk7ezAcv7simMXQw+afvqUlhdoyVM4QQuhj8
+KzqjNP3IC2fSHoFECWxGfC1fNcuqzRnzs98TqAy5BDnNXSW+e+CpenWtLpID/dvb
+azkeATfhMf/2KMd2Mahi6rnQ6IBnxhq1d5jLhYg00Ba1HbojEYOkCPKQlFV01bQw
+mUsyQ7sMr42JvdFTI4lDmQlHfqoexpFpLCDv4eUKjvG/K7xs0uLiF4vyMLVH5H/k
+6EF9HEP9sUF+aTDJXrrfHOUG1LR6/CkoMTI6cHJvdGVjdGVkLWF0MTU6MjAxMDEw
+MTRUMTUzNTM4KSkp
+=soiR
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/A2832820DC9F40751BDCD375BB0945BA33EC6B4C.asc b/tests/openpgp/privkeys/A2832820DC9F40751BDCD375BB0945BA33EC6B4C.asc
new file mode 100644
index 0000000..e69c27c
--- /dev/null
+++ b/tests/openpgp/privkeys/A2832820DC9F40751BDCD375BB0945BA33EC6B4C.asc
@@ -0,0 +1,17 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDExOnByaXZhdGUta2V5KDM6cnNhKDE6bjEyOToAx9HkS9EewRBeMrB/4u8wPapd
+l6spEli/46To7WcmBhmvEZJdG0ZQatYNvgkREqOadsgd49onjYaCkBSJtrJrSUOS
++Mo56Ff/52ejToFyfuZs6Ky0UGm9tvKEJw3aZiGNAZ5Pyvp+Jf+xLDwvj0xHHAj8
+lEEhOSrIrGvq4yx/+nUpKDE6ZTM6AQABKSgxOmQxMjg6DfYRUGbNEko1eq8wUEfM
+BBL6NRWlaf2/coVcLPIvCvASdlTWoog4KC7KiQOTKM07hp8Wz4u3hcDnMG/u60/u
+BPHPHCZThYlpGLVMhQwI46NZtMcRSNBp1rhJ5dt/FEcSFvseJOgce4PD/96bB3+c
+dbnvKcWM7ncRLj0wVfBzKeEpKDE6cDY1OgDanvj9klp9UkAgNwRxswOgiFOlGBsz
+J4dpCZHzWDCjYUd3eGWieynAnfuvctGTaMyB5xT7RwruntbgeRgPpejZKSgxOnE2
+NToA6fv/DFn2WVRAODQVQQGGxsvO2cM847IFJu96BbbxOLaZJ536RE980c2a9q/9
+B4hOYzKV4B4NI03u5/BqoOY8/SkoMTp1NjQ6ZIvWN1fksXhQMypVTLg8R81igqS3
+GXKmQ+KrVEfTIHnXKxH7tyfDeJSS6nfpfARhAe2mP3TIrbjX+9PR+QmkgykpKQ==
+=dUou
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/ADE710D74409777B7729A7653373D820F67892E0.asc b/tests/openpgp/privkeys/ADE710D74409777B7729A7653373D820F67892E0.asc
new file mode 100644
index 0000000..8a4fbf6
--- /dev/null
+++ b/tests/openpgp/privkeys/ADE710D74409777B7729A7653373D820F67892E0.asc
@@ -0,0 +1,17 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDExOnByaXZhdGUta2V5KDM6cnNhKDE6bjEyOToA5Hj2C3jzD8OGtLaw7+P2gYdA
+fR4s4YS3/AK+kYYtbm5EX4srysyUbylbQDQXUvRzw4FPkjXbboF6KjHw8icNWHCa
+zwSfPTfCDvi0JIildkfNqwBzCmNDRn++X8rvAeDCEJ/BtfcgfgmDTElSJOd+3B4X
+wnmtnBW54KlR42PLobspKDE6ZTM6AQABKSgxOmQxMjg6AkvpIaKimXAwf3G1m1nl
++LEDKdo55gosry8XToQakvdeXyUerCkplTS1uax8smOQUvrIPYvvnQZ7S9wuPli3
+FWH6l/O+2Cgdti99xTSPeJRBeCuf2vv3bAgu/0tyB8MZgRRM9j5NJCeGO7o4DwRg
+UkLWX2+R5p4daI2LRUfmV4EpKDE6cDY1OgDr3h6mXHrLT4qSNexzz8BAvK/PlHMA
+MAJcy76lXSkl92+c4BcpjFDr5Vpaq/VXoLC4L/IlnEEqY967pAycdLH7KSgxOnE2
+NToA9/lAf6hJ4dHQ6ux5BH8DImq2OjW+sK3tIzzf6fpVkPjDuqOYidm+OL2SFCJa
+ymSWdVq2gQYbkcdRXdGKVJWDQSkoMTp1NjQ6NeHBLEuc/VX+h3ifO1jyMlh+9nZs
+HLkQzUyi2HnrXJ224cjvgc312wvtBQMUyLARWuEuMVMAwWofjX+GZXLz0ikpKQ==
+=Rw+Y
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/B2BAA7144303DF19BB6FDE23781DD3FDD97918D4.asc b/tests/openpgp/privkeys/B2BAA7144303DF19BB6FDE23781DD3FDD97918D4.asc
new file mode 100644
index 0000000..e1db456
--- /dev/null
+++ b/tests/openpgp/privkeys/B2BAA7144303DF19BB6FDE23781DD3FDD97918D4.asc
@@ -0,0 +1,31 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDIxOnByb3RlY3RlZC1wcml2YXRlLWtleSgzOnJzYSgxOm4yNTc6AM0QnGL35Fvz
++RybOtdBOWPX8XHZ3CvPq0gr50pjtZGZLjlDe5Jf8oX24cGBVdFdILOlOglXNJX6
+Qz5WxNrZtU53vDfkgjA8flQXFqIlkxv2ZkjKP2S+Vgr9LjbrFxxWRlZY+XqMNahE
+jbfA9gLr1GG8gM7ABsU7O03/pR2q7iF/aDMKm8asN7+k4/tW11e5yZeQkc+aBz8z
+bhBCZ90jdfQr5jHQsJx9EOlrCWvDcnGojDXQBc2AflwuEJQHSHqPsy4E5KnMlpp8
+ZzFw2spfExWzNnEfZ/qQ9dXgnhdeNFmg/JRvgohreRExvO3yJiQMbH28UBTb/NBO
+e14F8j1XdfkpKDE6ZTM6AQABKSg5OnByb3RlY3RlZDI1Om9wZW5wZ3AtczJrMy1z
+aGExLWFlcy1jYmMoKDQ6c2hhMTg6kSqZ9Kag78g4OjE5NzM3NjAwKTE2OlKflmHj
+kP1iNdN0sAvT1dopNzM2OvOi7aAUszePhXP3b3zH60C9ygixV1MQIKMUTDlZkTFv
+uVwdyH8IsB5rwaIZV5kO9xOdTPZAUG+jw3i5vUJzVYb3tORlIQLMZl+cT6InABFm
+eZ0jC7n2i5qEGK5nb+7na4SRv7jOCDpvEvmX3UxYsx9OvnVq9ndNg0t95wDc8Yp4
+OuWQM56DoSmlfi8yvX8vdihp5XVqwvoKZNbXP17o0K2VjSBfWMW30mF+1MRVGZjj
+rji0TJA0747OQjYEVVi4Jyvd1Qd+Ao3QWkXm4TzeiRAOYKTy1g9+6mTpLr29IQPo
+Ljvea48pJK2YJM9FNoZUOA04Pv6n0w/CCSFMSGDJon8KATgTgkXFWlxhCEPqJxJL
+emruPGPIb3Qv05etKPjGyvxk7fm+5xBjpxU2Xwk6kUZOfuX9b8KkBWDBlBSSRV/w
+teH+vTVFG1ydDFoCbay4TzKIHRHwS93ME0L11GHLViXMD3tOG1BKudPD4JUxrHVa
+MFHKtkvfTEz6v4YPCCp84+cjrbOKhSabg6caNcD0rge7iFVN4BArs1B/akEN+E8i
+q3MoUv7lN6GC1XEiEvK/8NgDamwUtbRQfPyJizow4tJSWTm0SZdTlBrkdUgCgW2s
+2dTElthntFqGOpBj6AvxoUPpnKKUp4o1W97bqV4regz9g8iMSna+BrzfYMrt8AlB
+A4eKtYbjFS0aNzhDRJepATVh/DVsy4bm3XN5L5Lne5greOCRcIjmE6n2GOHjh4Y0
+/ba/hj4WKm2n63toXJlxJ1t1Db90qiH8ASn6Bgd6BR0NueIrYI+YJMoeG+NLjB2h
+Ag6rd+yyjLEqaxniJkz9lZvj1AmX0JX3hfC6q8I84ZUdQFyBVQIxeN8EsKeWh45c
+1bEgyecQx+PNmrEUa90OZpJt6V1mQhb2SCDBgSVpAGoI4N2J5NOJ8gm+plgLsMDT
+Q1xhmBNF67kVYmV+ljiOOCB9CluiR/i2STv75ydnuBkpKDEyOnByb3RlY3RlZC1h
+dDE1OjIwMTQxMTA0VDA4NDIzNCkpKQ==
+=1YfR
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/C6A6390E9388CDBAD71EAEA698233FE5E04F001E.asc b/tests/openpgp/privkeys/C6A6390E9388CDBAD71EAEA698233FE5E04F001E.asc
new file mode 100644
index 0000000..939e8ab
--- /dev/null
+++ b/tests/openpgp/privkeys/C6A6390E9388CDBAD71EAEA698233FE5E04F001E.asc
@@ -0,0 +1,27 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDExOnByaXZhdGUta2V5KDM6cnNhKDE6bjI1NzoAqBvNbHXRfWWcek7De5Xpw8bO
+d8KibdW2sE6F2ZeqifoTvLTDcv2lIGqqovKQuRV9x5UkUIY0RQ0F6uI0d/o3nBSt
+8H8JsUylzCoTeds4UiFgpRA+O+egd8DyE7sABtlmBXHApYa7Vl/I/sASuSKS1VQF
+0JzkWSzj+381GZDtSg7t2z+A+n9S0MmrSM4EtPHZ5aelr7CQ65FHhmOkebJqcfX/
+j6gVX1FaZnJGzDkfgWDybaZWU9JXs+KlrJnVm6lO2YXb54TBnE2wW5PVm30dSCab
+YoHrivL01NuCadhUI+oiAVfTg41H69dRCelt07x2lrnXXdIX1/Q58h/a4IawxSko
+MTplMzoBAAEpKDE6ZDI1Njog6qS8HovBCoLrvf1v9wg5YfWupIlKiWTGu/FgjF6D
+uthfhGOa4giRwuEbm/RzkT46NL1SGR0mAilM9zL/5Ro7cR8n7rAWq+PxCLIck6zB
+BDEY0QfmkfGtUTX1YBHexXXBDieDIdEP1hyUqUZhQuBObi/fS8E4pt4TMjLTCTo1
+XEqZxqvK11AD6y2GddnCtH8vTgUaALzxNks23nngDEAdaDfJMHobST4Jb9RYVHNN
+zsZnLkKRr+GIemOoRXlCvTmTaw+8Vh6vUq8OWB5jryNxmt64FtWAHpLcW0n5OE6S
+6OlndqM92Xe9NT12wu75Mn+qTYrVauSPQvVveZMakG/hKSgxOnAxMjk6AMNAbeJx
+Bb6BlIWYMYrpAhkuPBgB3HvS0wZQ/n0j8LLEh+BJI8xa9HgDz7LOJPo00w6ERHvb
+Q+8VVBP69wxwHFJSfxJsImqUmQYXgoA2n/6GAqfj4oFK/FAsFd350bkaFnZcSxqj
+hJai8JQPku0cZqPudfRzThX5XIBbynMBNqIxKSgxOnExMjk6ANxpdW6WqMrWGerg
+X1i4MQd9ofyyWaT2XaGrnwMJY1qUqAqPViqZWPpPmya8mVrT9XkajdtPUm0zVzeK
+IjEScdvoS/pwkIMmM2+GRCFCo9zrsExeqa1cQpc8GFDZgynZ9/jXWeRiidU1xTMt
+gANAiZWOb8Ww6ti9p+t96liUEB7VKSgxOnUxMjk6AK/BZIZC/C6GJyRhEoTBlzmn
+nSC5eC6MojPTOQwd5VIkeEq4illBE7DF/5gFw/fufn7s+0vicZx/8yLH1mFYkbwq
+DfuoY/Da5lnRFw6fGOj4N0ikS26FApjlh2DS09HtIFuNAhErr5PDPjF1F31XL/1M
+50jkxfKPamxMiEs8it0VKSkp
+=GHvX
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/C905D0AB6AE9655C5A35975939997BBF3325D6DD.asc b/tests/openpgp/privkeys/C905D0AB6AE9655C5A35975939997BBF3325D6DD.asc
new file mode 100644
index 0000000..d972814
--- /dev/null
+++ b/tests/openpgp/privkeys/C905D0AB6AE9655C5A35975939997BBF3325D6DD.asc
@@ -0,0 +1,13 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDIxOnByb3RlY3RlZC1wcml2YXRlLWtleSgzOmVjYyg1OmN1cnZlNzpFZDI1NTE5
+KSg1OmZsYWdzNTplZGRzYSkoMTpxMzM6QJASwJYtt7iJ0ho9ryWXzi6FYfC5KR+p
+uwXT8cWoMCuCKSg5OnByb3RlY3RlZDI1Om9wZW5wZ3AtczJrMy1zaGExLWFlcy1j
+YmMoKDQ6c2hhMTg6vuifz6Hv4GM4OjE5NzM3NjAwKTE2OpcAZjV5+F/YlpOPgp1b
+WQUpOTY6qFMSoZCpIVdpOB9iKNKcrowuxl4tpSya+TVyDRedFeYEJgrcUjLFa5qt
+Eqi/0/ceDijJBz1HGyZ1mRWwGOzCqhd/8ccVQlQp66GqO8x4Na9uYtfNurj1a7Gv
+kdi+aQ+UKSgxMjpwcm90ZWN0ZWQtYXQxNToyMDE0MTEwM1QxODA1MzApKSk=
+=FCvp
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/CEFC51AF91F68A2904FBFF62C4F075A4785B803F.asc b/tests/openpgp/privkeys/CEFC51AF91F68A2904FBFF62C4F075A4785B803F.asc
new file mode 100644
index 0000000..224ce95
--- /dev/null
+++ b/tests/openpgp/privkeys/CEFC51AF91F68A2904FBFF62C4F075A4785B803F.asc
@@ -0,0 +1,17 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDExOnByaXZhdGUta2V5KDM6cnNhKDE6bjEyOToAvkUCG0xYaTIkZiTwd1wCUF8a
+Q2+YdrBGjSfzCyB8DzbPozYA29eOAayDg9RuesQGISmFQ6YRSINsAogdNfZmKu8j
+VMp/2mRQR6necW4OKkdtdnAI8B6Qaj/clBJt990RahXcrXG13fa0n72TpRbxmUUs
+Y4KRpbCRm44rR9AAWPspKDE6ZTM6AQABKSgxOmQxMjg6IvI/yc3C60dXYh9kvzd6
+AVMGWt5zTVFhE+oDfMaxooW5q0tu6vHzViFeYmcxB4FbctnSbTNiN0RUIT7oxpGE
+AAumKRejGAaMwiKZz3bMV05l0LI0Yn10GzXsLtRx+iKzpUxThZETRU43BJeMqP5/
+rVqdQAu47pClgTwQWn6bXNkpKDE6cDY1OgDXtvl8CYDL/Q+9qZDCyItE5j7X4wRV
+en939fdDepuYAgsLLc7yqnDUOzajXWyx6PxygpnRs5cwmo2zbtZyyWKFKSgxOnE2
+NToA4c2I2FZT8gQLl9E3LF8TkBACZzsGb/t3mBUhYNSNZ7W6R/AkZARLI3IZOto5
+xhBrxfQayRISS2PBk390z3JlfykoMTp1NjQ6TamsumtzX7waNMzurt48kluI5Zy9
+isGpweGpp1T+4L+DiXMMAbhFW60gdqqo4+vzkn2M/M/8BPrKCw1TlDn3TSkpKQ==
+=lYo+
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/CF60965BF51F67CF80DECE853E0D2D343468571D.asc b/tests/openpgp/privkeys/CF60965BF51F67CF80DECE853E0D2D343468571D.asc
new file mode 100644
index 0000000..4f075d8
--- /dev/null
+++ b/tests/openpgp/privkeys/CF60965BF51F67CF80DECE853E0D2D343468571D.asc
@@ -0,0 +1,31 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDIxOnByb3RlY3RlZC1wcml2YXRlLWtleSgzOnJzYSgxOm4yNTc6AL8OibB/4Jrv
+yu3WLmT9knI/wEmxSjU6PXn7xCyDgxXd45szIKV3uURsYVsexrIRr5y+uijOWq2J
+FunrhNV4sCGpRAnS3EA1y1zqFx7Ob0/k4bLvNn8UFNtblIlxqSjT2Oz2T5+4GAme
+Vo7Z49keWryDyMeo+J1cio0NacBwR5Ee+DL6NfGoSyYYHrrQOn9PCnASR/I7THMP
+4l729yHnVNHnsgA1t/plvgXJj2Vf4KTu8NFaXFbd5a2gW14+nv2kUTenQuHs3Nn9
+d9NQeXSZ3tWP7FvthgklO3bp+dmjbynDKacKQGWKFyYlnx/qNKRe9Wnr59vVSeyk
+tyA0pbyvYNcpKDE6ZTM6AQABKSg5OnByb3RlY3RlZDI1Om9wZW5wZ3AtczJrMy1z
+aGExLWFlcy1jYmMoKDQ6c2hhMTg6LskYBR0oJSs4OjE5NzM3NjAwKTE2OtX507Od
+8u583SoOhgpvTDopNzM2OqQsv6qf5uCTG0KqleH7oUveFKt4ucEElrAyAiHe8x4c
+5BIt9r2cz9yVyZjiolXC2zuGZMmt15odX+1vp9zUAaK5cFFFk8z6qEBEeFOP+4Ss
+iBeI2r3fHN+/mYMlyomBXV9bZ3ER3lio8iqdsnjkqFo+AfA3otGvrZNhXPa6GaLh
+1KRW3D3Lg97gp+GwrsQ5sRQ6EFBlGzg2YFWLFGO1txvQfLECEzQMZaej1S6XNKY0
+87LmmCNhyNvSP7WECb0PMwlXKDUEy7zjEK2VkGRSEg4Y8CmMFeW68Zrlvivcy01E
+KXQ2EpI0i9mxI/QnQa/6d4GAkuPywbJG4U/rgEDMwubHhp+QVNpU6JWy2KKnMVVf
+7Ln5KMKCOKh3ZcvRYUq1yen8ybEOKJ2nFZ5VQfmSSXvW5yDClQCe8PwwOY1a5nw/
+ODcPM4oeW8PmWncWNuhme/uicECa0wuJ4IGUKTyg/Vs4OLMjiXLwT1gblPEcfuws
++3A3o494JOEqnyyvfM3ZmHE+RYe9+OV6/1JFsIhSn9cWty/H26QpuFvN5D2cXXKU
+txuqC8MmovtCRzG/ASja68rc0NC7uACBRvb90v5tlDCFmBZAPJmFnBnB/OGqQOmF
+dFXGRJiauaKOwRtEzC0wyMdkB5+j4/oBj4Nt3Ua5Qbk1B5m5M4YfEX4c89G635O0
+cmO+c9ubv/oQSNcXnJmIDnIvwBXDMzS9psQp/LzIpXIpbJUU1tRclUL/LAQChhmS
+Isq2qP/s8jg8BNSjiXlRkLqg5xkcKuW757y725fiAOrNjDYYBNVC1XIPaVc1/Fkm
+T1Mcn0OuQ9Hwcj7C+lqcq7vSZkx6h5+YjvJ5uDUQvFVJMfoDbKMKsKuJ2qSK7ano
+ePtji6v9SylT9cSZnSngaar+j55JD/wocGlAcVOZ+fOkoo81wWAJ1+XNZX4YNQ+/
+naNT4eyAq9k+CqxZjDOSbdg/aoOzFPDkRpDrkQGq1IcpKDEyOnByb3RlY3RlZC1h
+dDE1OjIwMTQxMTA0VDA4NDg1NykpKQ==
+=MG45
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/D69102E0F5AC6B6DB8E4D16DA8E18CF46D88CAE3.asc b/tests/openpgp/privkeys/D69102E0F5AC6B6DB8E4D16DA8E18CF46D88CAE3.asc
new file mode 100644
index 0000000..86f6acf
--- /dev/null
+++ b/tests/openpgp/privkeys/D69102E0F5AC6B6DB8E4D16DA8E18CF46D88CAE3.asc
@@ -0,0 +1,27 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDExOnByaXZhdGUta2V5KDM6cnNhKDE6bjI1NzoA255CUJxFEKLVwEoSgwZqXd94
+AhjGUbMY6NXdFj5cCq0JmWZrbpT/5OblTrymiH1iLmI0ymo+/s8vh6NtB98dhr1s
+yH3asNQfXZRfF+u5X5hLDNPF4sUelsl4+EUef0Hbc9U+e+8F8A9TMxELSqQ8Ul3H
+u42hc+/ugkc1G/8++Sv/f60TqWcUR2GmuiAvkuS1WmdATMhwPr7vMfssV0X0mboz
+32//b/UfuOyctso5FM+bRaKrEJDQ2WDg57yqnaqsKEgajW0jElpAVIn792W6YWKO
+k4auYSpO5f7BVs40Z+bxKGxiH87z9fnmlYAsQwPOOxZwWaCSrReeheK6c6emASko
+MTplMzoBAAEpKDE6ZDI1NjoYgHaQ5xkEJcvyhmZm/H8/doq9XnrkazZ7O5OimKsi
+Jx4BYZ4uGdeBd9/bbKFTwaauMBddrIQstNFuW5BIJt9KGgtvRC3y49JABClRJ45o
+mOVpSp3dkp+6s5hDHUsCvZvjN3D02LzxLx8u0lb6fopFp4rSD5dqB48KNTGQAbvK
+hqYZ521wmTfYLiy9taVAhqZLHlhfmrHYmdvvKjdNE3tSActlHWXdu119rdHhJ0zJ
+Rxx/N845rl+PXXdFHveQxCBhHBQpSUaKpte+ZbT4vrjyNugD6XjDi4HLI9CysUDP
+A0IFD+BJWw7NgYY51yamT7nNcMD6bJdgtt1FXbSgh7jVKSgxOnAxMjk6AN7btgbl
+HEHrKf77a9ptklDvd2bEkUOwj3bFavB1lpkliW1USoWMx97zjxRPzQOs6EoE7u9Z
+JRDO8xA9ZbI0WOk7io5OHpVp1BHyeqebqfxHzN5wsRphu+peg7vYfENVf0lA8LIU
+NeUkbfEWDQ+inXxqkgD51gPfrU3PRdCDM8fnKSgxOnExMjk6APxHMsTrjaUoITcI
+LqT35wDinFnX1+OgKD00krcUmc+G0ylLMolVxsB4yDVIkY8QfhbaGtFoP45PCnxS
+rvHKrTt/6sZJCWXf+3KaN0QSxyfi/mEPj3KbXhmaY6x8R4aB/M7ipLXNdj/308pu
+a50YPwIYyX0L0qoRBBo/xQDgOsXXKSgxOnUxMjk6AMzWw92nzShDRzPZwBvb48YY
+YzZFiFtJbcZ1n8DaiM7VmzAkRqwmCu6HPP/8IC4d6UkFUUlHyDyxSaKuA45Y+FR1
+Pb2/Y/mQVsBanK4i+1oL4fYGexFO0qjA+8l2+6BEWbKQX60nIcFXD2hAP0aqWDGO
+lXrPhpWPRrwDd4j9DEvfKSkp
+=1cwG
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/DF00E361D34F80868D06879AC21D7A7D4E4FAD76.asc b/tests/openpgp/privkeys/DF00E361D34F80868D06879AC21D7A7D4E4FAD76.asc
new file mode 100644
index 0000000..0bf0006
--- /dev/null
+++ b/tests/openpgp/privkeys/DF00E361D34F80868D06879AC21D7A7D4E4FAD76.asc
@@ -0,0 +1,31 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDIxOnByb3RlY3RlZC1wcml2YXRlLWtleSgzOnJzYSgxOm4yNTc6AK5ASAwdxvm1
+x0sD1PVAjVCEgo2oqT3mg/onopj3t3dVlBuEv23f+5/EoLTEIAE8ulGDCBQRw70X
+j4e5B87oc5DxBs2uiMGbCX8L7cEQuXVRRrwQR5kJI62iCle1prehdXTWFgZUBXwQ
+60GAGeft/MmznrUN4qy1qt7dp8eqOq9on9xA8uKzigCYEjRsGeScrFedAemg0so6
+AWbCSz6S1BbZKxYPilbG7VMvpA24kgPqQiiaZESlFt7iey04WE9v26vH5CExVqFl
++M+tAGIPw439X0leIpdidTWFdREw7DCkRBjZ8cWbLEIfhErco1mqlSxR1AvlSXnb
+yxerHQRO+KspKDE6ZTM6AQABKSg5OnByb3RlY3RlZDI1Om9wZW5wZ3AtczJrMy1z
+aGExLWFlcy1jYmMoKDQ6c2hhMTg6tIGQBN/WvYA4OjE5NzM3NjAwKTE2Olq8YLkU
+7sO9zkXVYdR0ApwpNzM2OneDiO9TEO0M//ms4Wh2ZDR/oOHF67pj9woAkW+en7vv
+r512xqgFV2m2b2aFTJYgeJwWJgVItmgmoM4RsbtL3CVSXrKRi4fi3VbwWEN0p4MI
+wOXkbdFFxywvEQjQoNEvvBFHTlLkRIHzugfhUJID4wNzcGq55LnH1zoyXdUorlhi
+dpJ7Y1QHjm7j3RBiTRpGXXOIwQkpTf4eNIIsOeaDTQVIhTh62UFzUY26NBftx0mC
+cYhFs0lOk7k482OnCkm712BejhvHOcs46Lhi9JwfY6j8QcgrIp4b2MyT8BOg1cIX
+vjD39tKJYh9SHWZlB694KZYqSmlr+RfhgLTNV7Oq4Il9JNhPgImG/ouE/O14j8W9
+MyIg7T8NhvYRt+sym9oijvxXb8Z7dD12RomxOZFAajrHMv349JAebUOSIxCBg082
+LNRleJKl7s8Dw5avgyc03kqAUageGOjRWsJvbSKLebKDUoLqEyyNiTNbbTru4oZb
+RyfqPftZkPymIQGS7rukohZ7cZHM8jT4Bf79VRvFAXQJ8IVGjHVvrwEbV0mOgin7
+i3n0hYsO8t3YvNtQZ6c2oTkhaeakYgebRKXSgWmLK/FcCtnftYuulPD/ApkcnGFa
+jqJcxKT6vNbsrp+YOlder0cZz7S+1qXkKP9iGuVUa6uG818pv4IZrrgWJP85ZUqj
+PV5Dy9QYQbd8HHxrDkWQ6xMdFM0049KZeNuKGnbv2gz27RUMf7U7eyj7QBuDCHwL
+Q3UHOXr5Db7bDepCOXBdjTxET2BzotOkn/pbNJN1wAa3UZB3ovFWo7vOwQCF1+nY
+AWAUxNm8W07SzBVZuCHxPsnMX8z501jz1f8yiKgDgG6JtCCESTIPnOj+7k+86eYV
+CXfgf3klgcruOTXCZwaUhQYEf7Rxyln8FoMD/5VoKWAIwUsbpMquhwbZmmq6nada
+owEctivvDKqlXNf5vREV76+OTpiFSpRDiX5cwWU/eG4pKDEyOnByb3RlY3RlZC1h
+dDE1OjIwMTQxMTA0VDA4NDMyMykpKQ==
+=3wKz
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/EB33B687EB8581AB64D04852A54453E85F3DF62D.asc b/tests/openpgp/privkeys/EB33B687EB8581AB64D04852A54453E85F3DF62D.asc
new file mode 100644
index 0000000..ede9a91
--- /dev/null
+++ b/tests/openpgp/privkeys/EB33B687EB8581AB64D04852A54453E85F3DF62D.asc
@@ -0,0 +1,10 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+KDExOnByaXZhdGUta2V5KDM6ZWNjKDU6Y3VydmUxMDpDdXJ2ZTI1NTE5KSg1OmZs
+YWdzOTpkamItdHdlYWspKDE6cTMzOkAWeeZlz31O4qTmIKr3CZhlRUXZFxc3YKyo
+CXyIZBBRaykoMTpkMzI6VN/VGmlcwGBPcLTya2hfU4t37nMcFCKdNSXjJ5DFA0Ap
+KSk=
+=eVhB
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/privkeys/FD692BD59D6640A84C8422573D469F84F3B98E53.asc b/tests/openpgp/privkeys/FD692BD59D6640A84C8422573D469F84F3B98E53.asc
new file mode 100644
index 0000000..7b25b7a
--- /dev/null
+++ b/tests/openpgp/privkeys/FD692BD59D6640A84C8422573D469F84F3B98E53.asc
@@ -0,0 +1,15 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v1.4.8 (GNU/Linux)
+Comment: Use "gpg --dearmor" for unpacking
+
+KDExOnByaXZhdGUta2V5KDM6ZHNhKDE6cDk3OgDbbxWAbWsheUJprK6VryMTpwDi
+YwMfL+92nrHqSfPqlpMWgDTia8qnpRSXbyEmSppp/6/Ygp+N3n32Kznq7PjHXiuW
+LlZGvZMtzmvaMA17y0GY6oLBxS7rhASXIKa9hEUpKDE6cTIxOgD/igRZcqjTHbCv
+I/mTtAPK5yJhqykoMTpnOTc6ALV10OZ7mJkWRMRYeGu1T3uwS7YYORJAHwd1fwKh
+Fys7P8HZaWIXqp8EqFxk8VUEiEo3ONN9jtIRgBmTbNywKbx6WfBItoYTPEoU0UGo
+oM1c/5rfmylyqwdIbMNXDhW4oykoMTp5OTc6AJNnAP6skpHlhVAmecLZT9eRzVoO
+q1ivUIntK2Mh47qsL74q6BBwz2sviPU2Y3pDlbb6Ed0qJAXvdCT24hlfoGoXzkoD
+InkPJTJeL0gCnwmQPjvXFFd71Cvg5LaL4lIQLSkoMTp4MjA6cZuCxaj7sT+FZqTO
+y2lNfMjaQMgpKSk=
+=s5nv
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/pubdemo.asc b/tests/openpgp/pubdemo.asc
new file mode 100644
index 0000000..d550f1a
--- /dev/null
+++ b/tests/openpgp/pubdemo.asc
@@ -0,0 +1,566 @@
+26 demo keys:
+
+pub 1024D/68697734 1999-03-08 Alpha Test (demo key) <alpha@example.net>
+uid Alice (demo key)
+uid Alfa Test (demo key) <alfa@example.net>
+sub 1024g/46A871F8 1999-03-08
+pub 1024D/1AFDAB6C 1999-03-08 Charlie Test (demo key) <charlie@example.net>
+sub 1024g/BC43DA60 1999-03-08
+pub 1024D/FAEF6D1B 1999-03-08 Echo Test (demo key) <echo@example.net>
+uid Eve (demo key)
+uid Echelon (demo key)
+sub 1024g/7272144D 1999-03-08
+pub 1024D/8FC282E6 1999-03-08 Golf Test (demo key) <golf@example.net>
+sub 1024g/9DCAD354 1999-03-08
+pub 1024D/04259677 1999-03-08 India Test (demo key) <india@example.net>
+sub 1024g/61F76C73 1999-03-08
+pub 1024D/43C2D0C7 1999-03-08 Kilo Test (demo key) <kilo@example.net>
+sub 1024g/9AF64D02 1999-03-08
+pub 1024D/A9E3B0B2 1999-03-08 Bravo Test (demo key) <bravo@example.net>
+uid Bob (demo key)
+sub 1024g/E29BA37F 1999-03-08
+pub 1024D/EB9DC9E6 1999-03-08 Delta Test (demo key) <delta@example.net>
+sub 1024g/B0C45424 1999-03-08
+pub 1024D/7372E243 1999-03-08 Foxtrot Test (demo key) <foxtrot@example.net>
+sub 1024g/EE45198E 1999-03-08
+pub 1024D/34C6E3F1 1999-03-08 Hotel Test (demo key) <hotel@example.net>
+sub 1024g/D622AD0A 1999-03-08
+pub 1024D/D2699313 1999-03-08 Juliet Test (demo key) <juliet@example.net>
+sub 1024g/35F8F136 1999-03-08
+pub 1024D/B79103F8 1999-03-08 Lima Test (demo key) <lima@example.net>
+sub 1024g/FE56350C 1999-03-08
+pub 1024D/BE5CF886 1999-03-08 Mike Test (demo key) <mike@example.net>
+uid Mallory (demo key)
+sub 1024g/4F31EAE8 1999-03-08
+pub 1024D/30CEC684 1999-03-08 November Test (demo key) <november@example.net>
+sub 1024g/8B70E472 1999-03-08
+pub 1024D/6D9732AC 1999-03-08 Oscar Test (demo key) <oscar@example.net>
+sub 1024g/2681619F 1999-03-08
+pub 1024D/3FF13206 1999-03-08 Papa test (demo key) <papa@example.net>
+sub 1024g/63330D9C 1999-03-08
+pub 1024D/3C661C84 1999-03-08 Quebec Test (demo key) <quebec@example.net>
+sub 1024g/A029ACF4 1999-03-08
+pub 1024D/777FBED3 1999-03-08 Romeo Test (demo key) <romeo@example.net>
+sub 1024g/11D102EA 1999-03-08
+pub 1024D/A3AE3EA1 1999-03-08 Sierra Test (demo key) <sierra@example.net>
+sub 1024g/0F1B50B4 1999-03-08
+pub 1024D/85A81F38 1999-03-08 Tango Test (demo key) <tango@example.net>
+sub 1024g/101C0402 1999-03-08
+pub 1024D/653244D6 1999-03-08 Uniform Test (demo key) <uniform@example.net>
+sub 1024g/5522BDB9 1999-03-08
+pub 1024D/61F04784 1999-03-08 Victor Test (demo key) <victor@example.org>
+sub 1024g/07287134 1999-03-08
+pub 1024D/EC67DBDE 1999-03-08 Whisky Test (demo key) <whisky@example.net>
+sub 1024g/FD6E27F6 1999-03-08
+pub 1024D/567FB34A 1999-03-08 XRay Test (demo key) <xray@example.net>
+sub 1024g/41E408BE 1999-03-08
+pub 1024D/4B11B25F 1999-03-08 Yankee Test (demo key) <yankee@example.net>
+sub 1024g/F7B080AD 1999-03-08
+pub 1024D/54ACD246 1999-03-08 Zulu Test (demo key) <zulu@example.net>
+sub 1024g/A172C881 1999-03-08
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v0.9.3 (GNU/Linux)
+Comment: For info see http://www.gnupg.org
+
+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
+=1N8S
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/pubring.asc b/tests/openpgp/pubring.asc
new file mode 100644
index 0000000..a091e0e
--- /dev/null
+++ b/tests/openpgp/pubring.asc
@@ -0,0 +1,720 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.3.5-cvs (GNU/Linux)
+
+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
+wRjlQVX31vkPxZDR2UBoHjBYDg==
+=XVtd
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/pubring.pkr.asc b/tests/openpgp/pubring.pkr.asc
new file mode 100644
index 0000000..e8eaabb
--- /dev/null
+++ b/tests/openpgp/pubring.pkr.asc
@@ -0,0 +1,28 @@
+This is a test pubring generated by pgp 5 beta
+
+Type Bits KeyID Created Expires Algorithm Use
+sec+ 768 439F02CA 1998-03-17 ---------- DSS Sign and Encrypt
+sub 768 CB879DE9 1998-03-17 ---------- Diffie-Hellman
+uid pgp5 test <pgp5@dev.null>
+
+
+-----BEGIN PGP ARMORED FILE-----
+Version: GNUPG v0.2.13a (Linux)
+Comment: This is an alpha version!
+Comment: Use "gpgm --dearmor" for unpacking
+
+mQFCBDUOrE4RAwDbbxWAbWsheUJprK6VryMTpwDiYwMfL+92nrHqSfPqlpMWgDTia8qnpRSXbyEm
+Sppp/6/Ygp+N3n32Kznq7PjHXiuWLlZGvZMtzmvaMA17y0GY6oLBxS7rhASXIKa9hEUAoP+KBFly
+qNMdsK8j+ZO0A8rnImGrAwC1ddDme5iZFkTEWHhrtU97sEu2GDkSQB8HdX8CoRcrOz/B2WliF6qf
+BKhcZPFVBIhKNzjTfY7SEYAZk2zcsCm8elnwSLaGEzxKFNFBqKDNXP+a35spcqsHSGzDVw4VuKMD
+AJNnAP6skpHlhVAmecLZT9eRzVoOq1ivUIntK2Mh47qsL74q6BBwz2sviPU2Y3pDlbb6Ed0qJAXv
+dCT24hlfoGoXzkoDInkPJTJeL0gCnwmQPjvXFFd71Cvg5LaL4lIQLbABh7QZcGdwNSB0ZXN0IDxw
+Z3A1QGRldi5udWxsPrABA4kASwQQEQIACwUCNQ6sTgQLAwECAAoJENY0E25DnwLKxIoAoPSyM/Mw
+BogpyMU5YY+Sj74k3UIfAJ0RopQa8ciickDVzoSVPrGysrnOkLABZ7kAzQQ1DqxWEAMA/wVrlNsP
+qTxWZbUiMrUN8MjTFR2xUhuTw3cdvRgiVPUT/q1l1+I3CpopVBx/XuAkg5sHB80zc6pZg652YFV3
+dLoTceS7ridb5k23sHa2hZGCeTo6AdxIOy53giCPDP9FAAICAv9Oh5/OVxUqI+6hsp9ccOEhRA9N
+8aJzYDPjvCQyhgej2P1kTsBZqWIx0/PiMvIt+qqhT2YfyD68mHIBztScAXZKTnjroUPKl0+bkX09
+NbdyqojAkzhaCRKUzwnaHEfhi2WwAYeJAD8DBRg1DqxW1jQTbkOfAsoRAnaPAJ0Z/k6Y2ypgDhXo
+qBLeW7Lq/AKYEACeLTod6Nt117DkqDz9epmIqwWOE1ewAWc=
+=6BrN
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/quick-key-manipulation.scm b/tests/openpgp/quick-key-manipulation.scm
new file mode 100755
index 0000000..6cdf19a
--- /dev/null
+++ b/tests/openpgp/quick-key-manipulation.scm
@@ -0,0 +1,228 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016-2017 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(load (with-path "time.scm"))
+(setup-environment)
+
+(define (exact id)
+ (string-append "=" id))
+
+(define (count-uids-of-secret-key id)
+ (length (filter (lambda (x) (and (string=? "uid" (car x))
+ (not (string=? "r" (cadr x)))))
+ (gpg-with-colons
+ `(--with-fingerprint
+ --list-secret-keys ,(exact id))))))
+
+(define alpha "Alpha <alpha@invalid.example.net>")
+(define bravo "Bravo <bravo@invalid.example.net>")
+(define charlie "Charlie <charlie@invalid.example.net>")
+(define delta "Delta <delta@invalid.example.net>")
+(define deltahash "359DC5EFF98B14A58AAA615C638E8BD0CEDA537B")
+
+(define (key-data key)
+ (filter (lambda (x) (or (string=? (car x) "pub")
+ (string=? (car x) "sub")))
+ (gpg-with-colons `(-k ,key))))
+
+(setenv "PINENTRY_USER_DATA" "test" #t)
+
+(info "Checking quick key generation...")
+(call-check `(,@GPG --quick-generate-key ,alpha))
+
+(define keyinfo (gpg-with-colons `(-k ,(exact alpha))))
+(define fpr (:fpr (assoc "fpr" keyinfo)))
+
+(assert (= 1 (count-uids-of-secret-key alpha)))
+(assert (not (equal? "" (:expire (assoc "pub" keyinfo)))))
+
+(info "Checking that we can add a user ID...")
+
+;; Make sure the key capabilities don't change when we add a user id.
+;; (See bug #2697.)
+(let ((pre (key-data (exact alpha)))
+ (result (call-check `(,@GPG --quick-add-uid ,(exact alpha) ,bravo)))
+ (post (key-data (exact alpha))))
+ (if (not (equal? pre post))
+ (begin
+ (display "Key capabilities changed when adding a user id:")
+ (newline)
+ (display " Pre: ")
+ (display pre)
+ (newline)
+ (display " Post: ")
+ (display post)
+ (newline)
+ (exit 1))))
+
+(assert (= 2 (count-uids-of-secret-key alpha)))
+(assert (= 2 (count-uids-of-secret-key bravo)))
+
+(info "Checking that we can mark an user ID as primary.")
+(call-check `(,@gpg --quick-set-primary-uid ,(exact alpha) ,alpha))
+(call-check `(,@gpg --quick-set-primary-uid ,(exact alpha) ,bravo))
+;; XXX I don't know how to verify this. The keylisting does not seem
+;; to indicate the primary UID.
+
+(info "Checking that we get an error making non-existent user ID the primary one.")
+(catch '()
+ (call-check `(,@GPG --quick-set-primary-uid ,(exact alpha) ,charlie))
+ (error "Expected an error, but get none."))
+
+(info "Checking that we can revoke a user ID...")
+(call-check `(,@GPG --quick-revoke-uid ,(exact bravo) ,alpha))
+
+(info "Checking that we can revoke a user ID by its hash...")
+(call-check `(,@GPG --quick-add-uid ,(exact bravo) ,delta))
+(call-check `(,@GPG --quick-revoke-uid ,(exact bravo) ,deltahash))
+
+(info "Checking that we get an error revoking a non-existent user ID.")
+(catch '()
+ (call-check `(,@GPG --quick-revoke-uid ,(exact bravo) ,charlie))
+ (error "Expected an error, but get none."))
+
+(info "Checking that we get an error revoking the last valid user ID.")
+(catch '()
+ (call-check `(,@GPG --quick-revoke-uid ,(exact bravo) ,bravo))
+ (error "Expected an error, but get none."))
+
+(assert (= 1 (count-uids-of-secret-key bravo)))
+
+(info "Checking that we can change the expiration time.")
+
+(define (expiration-time id)
+ (:expire (assoc "pub" (gpg-with-colons `(-k ,id)))))
+
+;; Remove the expiration date.
+(call-check `(,@gpg --quick-set-expire ,fpr "0"))
+(assert (equal? "" (expiration-time fpr)))
+
+;; Make the key expire in one year.
+(call-check `(,@gpg --quick-set-expire ,fpr "1y"))
+(assert (time-matches? (+ (get-time) (years->seconds 1))
+ (string->number (expiration-time fpr))
+ (minutes->seconds 5)))
+
+
+;;
+;; Check --quick-addkey
+;;
+
+;; Get the subkeys.
+(define (get-subkeys)
+ (filter (lambda (x) (equal? "sub" (car x)))
+ (gpg-with-colons `(-k ,fpr))))
+
+;; This keeps track of the number of subkeys.
+(define count (length (get-subkeys)))
+
+(for-each-p
+ "Checking that we can add subkeys..."
+ (lambda (args check)
+ (set! count (+ 1 count))
+ (call-check `(,@gpg --quick-add-key ,fpr ,@args))
+ (let ((subkeys (get-subkeys)))
+ (assert (= count (length subkeys)))
+ (if check (check (last subkeys)))))
+ ;; A bunch of arguments...
+ '(()
+ (- - -)
+ (default default never)
+ (rsa "sign auth encr" "seconds=600") ;; GPGME uses this
+ (rsa "auth,encr" "2") ;; "without a letter, days is assumed"
+ ;; Sadly, the timestamp is truncated by the use of time_t on
+ ;; systems where time_t is a signed 32 bit value.
+ (rsa "sign" "2038-01-01") ;; unix millennium
+ (rsa "sign" "20380101T115500") ;; unix millennium
+ ;; Once fixed, we can use later timestamps:
+ ;; (rsa "sign" "2105-01-01") ;; "last year GnuPG can represent is 2105"
+ ;; (rsa "sign" "21050101T115500") ;; "last year GnuPG can represent is 2105"
+ (rsa sign "2d")
+ (rsa1024 sign "2w")
+ (rsa2048 encr "2m")
+ (rsa4096 sign,auth "2y")
+ (future-default))
+ ;; ... with functions to check that the created key matches the
+ ;; expectations (or #f for no tests).
+ (list
+ #f
+ #f
+ (lambda (subkey)
+ (assert (equal? "" (:expire subkey))))
+ (lambda (subkey)
+ (assert (= 1 (:alg subkey)))
+ (assert (string-contains? (:cap subkey) "s"))
+ (assert (string-contains? (:cap subkey) "a"))
+ (assert (string-contains? (:cap subkey) "e"))
+ (assert (time-matches? (+ (get-time) 600)
+ (string->number (:expire subkey))
+ (minutes->seconds 5))))
+ (lambda (subkey)
+ (assert (= 1 (:alg subkey)))
+ (assert (string-contains? (:cap subkey) "a"))
+ (assert (string-contains? (:cap subkey) "e"))
+ (assert (time-matches? (+ (get-time) (days->seconds 2))
+ (string->number (:expire subkey))
+ (minutes->seconds 5))))
+ (lambda (subkey)
+ (assert (= 1 (:alg subkey)))
+ (assert (string-contains? (:cap subkey) "s"))
+ (assert (time-matches? 2145960000 ;; UTC 2038-01-01 12:00:00
+ ;; 4260254400 ;; UTC 2105-01-01 12:00:00
+ (string->number (:expire subkey))
+ ;; GnuPG choses the middle of the day (local time)
+ ;; when no hh:mm:ss is specified
+ (days->seconds 1))))
+ (lambda (subkey)
+ (assert (= 1 (:alg subkey)))
+ (assert (string-contains? (:cap subkey) "s"))
+ (assert (time-matches? 2145959700 ;; UTC 2038-01-01 11:55:00
+ ;; 4260254100 ;; UTC 2105-01-01 11:55:00
+ (string->number (:expire subkey))
+ (minutes->seconds 5))))
+ (lambda (subkey)
+ (assert (= 1 (:alg subkey)))
+ (assert (string-contains? (:cap subkey) "s"))
+ (assert (time-matches? (+ (get-time) (days->seconds 2))
+ (string->number (:expire subkey))
+ (minutes->seconds 5))))
+ (lambda (subkey)
+ (assert (= 1 (:alg subkey)))
+ (assert (= 1024 (:length subkey)))
+ (assert (string-contains? (:cap subkey) "s"))
+ (assert (time-matches? (+ (get-time) (weeks->seconds 2))
+ (string->number (:expire subkey))
+ (minutes->seconds 5))))
+ (lambda (subkey)
+ (assert (= 1 (:alg subkey)))
+ (assert (= 2048 (:length subkey)))
+ (assert (string-contains? (:cap subkey) "e"))
+ (assert (time-matches? (+ (get-time) (months->seconds 2))
+ (string->number (:expire subkey))
+ (minutes->seconds 5))))
+ (lambda (subkey)
+ (assert (= 1 (:alg subkey)))
+ (assert (= 4096 (:length subkey)))
+ (assert (string-contains? (:cap subkey) "s"))
+ (assert (string-contains? (:cap subkey) "a"))
+ (assert (time-matches? (+ (get-time) (years->seconds 2))
+ (string->number (:expire subkey))
+ (minutes->seconds 5))))
+ #f))
diff --git a/tests/openpgp/run-tests.scm b/tests/openpgp/run-tests.scm
new file mode 100644
index 0000000..d4914bd
--- /dev/null
+++ b/tests/openpgp/run-tests.scm
@@ -0,0 +1,42 @@
+;; Test-suite runner.
+;;
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(if (string=? "" (getenv "abs_top_srcdir"))
+ (begin
+ (echo "Environment variable 'abs_top_srcdir' not set. Please point it to"
+ "tests/openpgp.")
+ (exit 2)))
+
+;; Set objdir so that the tests can locate built programs.
+(setenv "objdir" (getcwd) #f)
+
+(define setup
+ (make-environment-cache (test::scm
+ #f
+ (path-join "tests" "openpgp" "setup.scm")
+ (in-srcdir "tests" "openpgp" "setup.scm"))))
+
+(define tests (filter (lambda (arg) (not (string-prefix? arg "--"))) *args*))
+
+(run-tests (if (null? tests)
+ (load-tests "tests" "openpgp")
+ (map (lambda (name)
+ (test::scm setup
+ (path-join "tests" "openpgp" name)
+ (in-srcdir "tests" "openpgp" name))) tests)))
diff --git a/tests/openpgp/samplekeys/E657FB607BB4F21C90BB6651BC067AF28BC90111.asc b/tests/openpgp/samplekeys/E657FB607BB4F21C90BB6651BC067AF28BC90111.asc
new file mode 100644
index 0000000..a4772d4
--- /dev/null
+++ b/tests/openpgp/samplekeys/E657FB607BB4F21C90BB6651BC067AF28BC90111.asc
@@ -0,0 +1,45 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2
+
+mI0EVl9ZyAEEAL5FAhtMWGkyJGYk8HdcAlBfGkNvmHawRo0n8wsgfA82z6M2ANvX
+jgGsg4PUbnrEBiEphUOmEUiDbAKIHTX2ZirvI1TKf9pkUEep3nFuDipHbXZwCPAe
+kGo/3JQSbffdEWoV3K1xtd32tJ+9k6UW8ZlFLGOCkaWwkZuOK0fQAFj7ABEBAAG0
+I0JhcnJldHQgQnJvd24gPGJhcnJldHRAZXhhbXBsZS5vcmc+iLkEEwEIACMFAlZf
+WcgCGwMHCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIXgAAKCRC8Bnryi8kBEe5MA/9x
+kAkLHRAw7ctTqp+ecHiOrqdXWbt9xJ0EHQX2M1wkWjqAHLEGIfPDGmO0G8MmwZhu
+mAQetr258lPrcUOZ86xhpy9dacLRFf+Uk0R3nYSbYHFFht64NQFv2dvH6XaR1DfS
+6tnmu0L0BY3qN0BZJHZcVn5mUA8cvOwqSUDKB8k6ebiNBFZfWcgBBADH0eRL0R7B
+EF4ysH/i7zA9ql2XqykSWL/jpOjtZyYGGa8Rkl0bRlBq1g2+CRESo5p2yB3j2ieN
+hoKQFIm2smtJQ5L4yjnoV//nZ6NOgXJ+5mzorLRQab228oQnDdpmIY0Bnk/K+n4l
+/7EsPC+PTEccCPyUQSE5Ksisa+rjLH/6dQARAQABiJ8EGAEIAAkFAlZfWcgCGwwA
+CgkQvAZ68ovJARH0kQP+IMq61Zg+kBU6eL9eKZErcMtMWuddi1KCi8gAe8V7ZmcU
+8sIjKcKewDBgxmYz5siZzf993f4D0aqC/2XrNLnkuQ2P6XzpKZI2CKZXpbJH2eB0
+1F347MjDBA7P3vTwdzfVYklD3MAFC3Q42VGjbCx+OwVcODPZNfWAycQcYBvXS9G4
+jQRWX1rrAQQAqCYxh+c0mGKVkNRLiSe19rSbOgLVJcL6dH1EnawO6klyypIbrDom
+7DNNTlp7TMlwQ+UsKbmT8jwkU08/awg6W9Wq5LCABUStYrVcwJJlf3p4lBru0BSR
+laKuIslpk5Powfj2lPXX6o1eRHsnxk9FTD+MGcWkhfL9HF+Rq8vPcicAEQEAAYkB
+PQQYAQgACQUCVl9a6wIbAgCoCRC8Bnryi8kBEZ0gBBkBCAAGBQJWX1rrAAoJEBFB
+v3/193uDNhkEAIdnkbx6fKxEG6SX/GS/tBRFvvICDt9yGOJd+jmMPZoUODfd0Gkl
+sO7FHRDLL2nyXgz2vhiRBDuboeG8h3oi8QPSi+cg7+EwpVMVFKpEOrtdUVXCR+oo
+TLzD6z4dvdmE3+u6qrtKzkz5CsJ9CrEa0khR0b/We7GFQIpVyoD9NtNiQIkD/RX/
+oNkRG87K2TlTiObMJl7hB1Bk7Sm/E5Pl3knoCkjyo2vkmdK/bVlGBNimDlPh/r1a
+ab/HTeBFjP+pMhqoLZZ8sp4gZ88wsG7AE9FxtRxQEuJKEKAz6rYFK+zl2bfSlSAn
+KL1g5PAQujyLkq8qLJHrZn1imUIsBE6eOyiOWQi2uI0EVl9blQEEAOR49gt48w/D
+hrS2sO/j9oGHQH0eLOGEt/wCvpGGLW5uRF+LK8rMlG8pW0A0F1L0c8OBT5I1226B
+eiox8PInDVhwms8Enz03wg74tCSIpXZHzasAcwpjQ0Z/vl/K7wHgwhCfwbX3IH4J
+g0xJUiTnftweF8J5rZwVueCpUeNjy6G7ABEBAAGInwQYAQgACQUCVl9blQIbDAAK
+CRC8Bnryi8kBESPWA/4gTmke4A3gieDvSRWCzQ5IFkr7B+4niPy6Qitlwmvy7Wdr
+xNSlZJpSN1UBBurIH4wcPV7nlKMuv60eb00llaBSH1HgAfcbyv35EC39Cgz5Ffaf
+7f6EgIPjMGw9Ca1VNEWsfZnPfTz/JPiYzjjyC6N7nhfav4XjXxdicDHUz1pJubiN
+BFZfbpwBBADp5d9IcHOO6yy/UB+oNE19QRD3VjFeDruvq0DhKyDAK9QDpVM6Y8CZ
+Zb0Kn9jh50Fmk6/ZGzS5+11BFIY5B97hw2DBzHcgG+2Ca5NxAg6p5q9+FVfxfx+Q
+R+w+gIhZLZdUqVE3Mz8QcbzzZSeI6D5k5vmoX4Psy/uKVburSITNCwARAQABiQE9
+BBgBCAAJBQJWX26cAhsCAKgJELwGevKLyQERnSAEGQEIAAYFAlZfbpwACgkQvKQ8
+RB6pdHlhowQA2zOO2inuV/Z4Hl5PCDljiChFrKlddXkkdD7vXbdRh2XrQXMttmWW
+9a2NoeYsI4GyRb0T9fT0c7hDgY1NY3k+UHB+ex33xH7X6YADW8mY01q2zJqec9IY
+P2eBAHZrHImlBGStWX+VVHGtZwsDvR/gxkZkYnN1GFPN2ll0z81O0CjjWAP/delj
+0OY6Vc00SxfKJPb1ralpLIEMgRJWOayISHt6J4L1EGVVFs3gs9dqBQQ++65Iw55L
+m4+nieZzExTvSvYVBRbdWBgIJ1mFElHEy2KfeWzMA88pTMBssmH3xIGlkub/guWc
+OZSqAC5pVGPYCcXie7mx1k+5DrnQUgaf11zdvzI=
+=Htgs
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/README b/tests/openpgp/samplekeys/README
new file mode 100644
index 0000000..f8a7e9e
--- /dev/null
+++ b/tests/openpgp/samplekeys/README
@@ -0,0 +1,33 @@
+
+no-creation-time.gpg A key with a zero creation time.
+ecc-sample-1-pub.asc A NIST P-256 ECC sample key.
+ecc-sample-1-sec.asc Ditto, but the secret keyblock.
+ecc-sample-2-pub.asc A NIST P-384 ECC sample key.
+ecc-sample-2-sec.asc Ditto, but the secret keyblock.
+ecc-sample-3-pub.asc A NIST P-521 ECC sample key.
+ecc-sample-3-sec.asc Ditto, but the secret keyblock.
+eddsa-sample-1-pub.asc An Ed25519 sample key.
+eddsa-sample-1-sec.asc Ditto, but as protected secret keyblock.
+dda252ebb8ebe1af-1.asc rsa4096 key 1
+dda252ebb8ebe1af-2.asc rsa4096 key 2 with a long keyid collision.
+whats-new-in-2.1.asc Collection of sample keys.
+e2e-p256-1-clr.asc Google End-end-End test key (no protection)
+e2e-p256-1-prt.asc Ditto, but protected with passphrase "a".
+E657FB607BB4F21C90BB6651BC067AF28BC90111.asc Key with subkeys (no protection)
+pgp-desktop-skr.asc Secret key with subkeys w/o signatures
+rsa-rsa-sample-1.asc RSA+RSA sample key (no passphrase)
+ed25519-cv25519-sample-1.asc Ed25519+CV25519 sample key (no passphrase)
+silent-running.asc Collection of sample secret keys (no passphrases)
+rsa-primary-auth-only.pub.asc rsa2408 primary only, usage: cert,auth
+rsa-primary-auth-only.sec.asc Ditto but the secret keyblock.
+
+
+Notes:
+
+- pgp-desktop-skr.asc is a secret keyblock without the uid and subkey
+ binding signatures. When exporting a secret key from PGP desktop
+ such a file is created which is then directly followed by a separate
+ armored public key block. To create such a sample concatenate
+ pgp-desktop-skr.asc and E657FB607BB4F21C90BB6651BC067AF28BC90111.asc
+- ecc-sample-2-sec.asc and ecc-sample-3-sec.asc do not have and
+ binding signatures either. ecc-sample-1-sec.asc has them, though.
diff --git a/tests/openpgp/samplekeys/authenticate-only.pub.asc b/tests/openpgp/samplekeys/authenticate-only.pub.asc
new file mode 100644
index 0000000..a08a003
--- /dev/null
+++ b/tests/openpgp/samplekeys/authenticate-only.pub.asc
@@ -0,0 +1,31 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQENBFg8F68BCAC5VS/59Nrg5mw+wEAnk/vi0CGI+K5rGTmyAruy/aiS4kYfUJiE
+Pq/JZYCeNQ9GTbJN5M+Fiv1bhw6xeEfl4FAC/A0Uo39fvUSLJH2V+8lT3GxXt8KR
+Yx8MvotvoKiG1DRvgnwRh1qibX6+htJahPwHDViUuFz0ZeEPWiCwuoMOELmiTsuE
+VZbQsv08BwCOzIc3M8s63TtwMCUe+MBhqfRjEu6/Gt7miuGGVFXB96ao2O9u1HsR
+7cUjgVQp6JwGLgIIijjy167Ms+fKZetqA9tzu1C1SAtNYiqmAUoqGG1YEjS7oApo
+AKmHD+LGCMUPg5d6bhw+NyHjDAFWJEYv3kG3ABEBAAG0NVRlc3QgS2V5IChkbyBu
+b3QgdXNlKSA8YXV0aGVudGljYXRlLW9ubHlAZXhhbXBsZS5vcmc+iQFOBBMBCAA4
+FiEEkn7zd/0aG295XkDAKoeRfY/7pJ8FAlg8F68CGwEFCwkIBwIGFQgJCgsCBBYC
+AwECHgECF4AACgkQKoeRfY/7pJ9+zAf9FVZknDCWCNY42+RIR36fq2l1Gs8KfMsX
+rNXtfYPtLqioP8fz2LE0LoudSsZMLVygonPG0ZAxdIUHXcFdUqPrEzs4fEyR4xae
+OSxui2Q/u6+9bi7eilYYzVNRWkuyx2TrRQZEjMXMnuJcWptGbRWs/ipRUZBHWfLl
+2udLl+0TRIL7hni06xVCHbwE5szcLoyzzvIowGVADXFqeG7nty7uRNZNAD+ZWMH2
+J0vspZlUSVi7z1VygzDI3U42SMJmVqnRmICsB3QLI8Ns4nxWXO2z8fheSFcrP+LA
+cY3W6JgnLCzvyuogxnWmd4fzr1iB3E2Hcy/sr0cgQ5wtuseQRhmTlrkBDQRYPBfZ
+AQgAtKcbBYrIqh3cRTqyZjMxw492RVQoFawYmpr1bQ4HphVGnT4IhJZQ4DAm1JJZ
+QjzwDQiZMc1wD9Om6UC/g8gUBuFCpLCobwBzjH4an/G3Cfa8zGz5ANAROo5i5T1j
+vgoFEFdVue/GpAmMNixz+0ItQBh9jiOC6IYk1yyv/OsTzsj6AHnH0XiDpGoTNkca
+tb6Mu1VcXTMNf620Mxj6c7WE7awxL6MwKIa7XQSgXaO+JnbB+5Szz1wZ1ZhlnDp3
+KOurlfcXIbZirEaqmRByb+V21Dj3icXOJEj1RUbyVNqBS8rhw17kSxcehw/6ZAMW
+ehDmhXO98VVUknS0Mf+OJBi2JwARAQABiQE2BBgBCAAgFiEEkn7zd/0aG295XkDA
+KoeRfY/7pJ8FAlg8F9kCGyAACgkQKoeRfY/7pJ+sawf/eSjxxAglAdolF9lK070u
+VmMgq4GFPqJ3RqJPUFjwEFFSYLXkiALnMGXDSmOfPqCQ4c+PWwumFhKCz4MXVDD8
+x6mi9Z+HlEwIMaCnckrSTuQ5OgwO/6vkhz42OcgMZ3WQnWfNVM8jbNP9vX1vroPe
+HLFaPGy9KJMM0Z/hlCIIeyK/a90zWlT5UMfRoqNQRbY/iiYdmpvf69I9PobGVbo/
+7ahZTumPWwjiGOztNXeuo5UUaAVVxMQBYKp2w3wil2sHzYfTfYUSMyh+oUFx4Xlz
+WF3bLzsafRaeuK1h5+JuvIcimvU5zWZtn0hOpiIXpZOoJvvM9r5D4ZRT5UX2blQ8
+Pw==
+=vt5C
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/authenticate-only.sec.asc b/tests/openpgp/samplekeys/authenticate-only.sec.asc
new file mode 100644
index 0000000..109a7a1
--- /dev/null
+++ b/tests/openpgp/samplekeys/authenticate-only.sec.asc
@@ -0,0 +1,60 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+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
+VDw/
+=vLFX
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/dda252ebb8ebe1af-1.asc b/tests/openpgp/samplekeys/dda252ebb8ebe1af-1.asc
new file mode 100644
index 0000000..ddae954
--- /dev/null
+++ b/tests/openpgp/samplekeys/dda252ebb8ebe1af-1.asc
@@ -0,0 +1,29 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+
+mQINBFJtd/UBEACpw/psXoGNM8RHczviD7FnGdjMQPEJQ+nuWQ2AEGYouulg5hFv
+0ChuSQVLiqQht2k5K2liyW1MeXoJ8tr9nSn/Zi9nttc0Wo6K7pvrDD40r2HNg305
+qLCzItr5st3x8cq2cIXvN4LOm2rqpBLZ/sqMmNiW2Y7/aAQqV1xtR35joHqamWHD
+UPOmzBMs07YSUjXgC1EMx8kWQSV6cuARj93kxWj8R6eoYHHfrWCEGR313wov6QST
+zIfVU7FqQqOmdLW3LaPHxcrI/TjsnkUN99qdlpjJH/YW925LDPJHAkliqPP5AvhU
+F9KbY2F8mcIZBCDd8TH+xXynuN3BbIU4kCwVbdx/tcpO1npuJcKB1Go/udyow/Ei
+Z3nHzJsCVkezvopek77wnwPaP0nAb7f4iIY3gJCoGirOx6N075TgF6MBe00q9oFE
+y4rvnUnU9/QzOOes95eUMhM+9eK1cuLFEV5t47DfxRdq+fQip3FJ2l6v19sZvQ0G
+j06pjYqg0of273rG8oXcDrFjb1Zqhj8x1mLl6u7d/ide5wTm9HylBWcYKQjIJJAi
+WIScxEPIOINDJKgsKTuKtoyNvISJ3xUeS1yzxiIb3YGLIyPgFFx0vFyqJfbkXq70
+m1n2xnJlkTidfzbZvc6EA7vRGSDYK6FqqhlGhc7UypUEVW8FM/jZNAOS6QARAUGt
+tCg5RTY2OTg2MTM2OEJDQTBCRTQyREFGN0REREEyNTJFQkI4RUJFMUFGiQI3BBMB
+CgAhBQJSg/uTAhsDBQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAAAoJEN2iUuu46+Gv
++Z0P+wQhkLwm+WGcEsS98Lei9O7hit/k4g/VkLUUQV7BOR3n8uRZIFkdOtpvrFU3
+aKf246uCy6GM48Oh+1U2cv5InX/WEuKaFo5uF6t79wyt18BUn1weDcU+DQdOSG4f
+fSnNa55wkN0l0svW4fGIthjmDTz6HZFntYD+9A20wZAqpPIs+vyG9Jp+e9E9Y/W/
+EFQbNlxHHb9+BMT2+DtNP+HSl3MPFlQPKOLZxyLAU5uzT0Sa0LxhrQy5FgkW6Jog
+sbAJVM9z0pZw+grzGPciM66ZW1rxeICvbYsdWLytRjqxpY8GS8XudyseUGd+dZim
+ptarsrE5yfSMg2gW5Z1PTc0tEMXJLUwtpyzQjpFpbb7dPuo2TUp09LgZKX63WCbS
+Nb1RTaGfkeYudOTo2rh4Jfg+Tb/JRpO6clo0rxAq8nPH2WmG+9TB8Zbb7YRzGWuV
+/e5SeVNR+zY8tXZKnmUIH1HIprc+BtT6Bupdvd0CT14Mg9MmsFvUXofwHLa4gahr
+8/iG9y3uHSA6Rhz++yOpyOmNvO1LDxsYNaRCIXQJbqgNwF5YNYlMPsEeY/CG7FOb
+Afv7rHiYtRRQfz2P4OF900DJO7QL9gdNXJ1+Hajy/5Lvvl7qwqMG4GvVQEsgFc5O
+jjFCUhE2i20j2kEMxvA5RLBH/fOoGARn87tiKSfb+pqLNZQb
+=fDJ8
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/dda252ebb8ebe1af-2.asc b/tests/openpgp/samplekeys/dda252ebb8ebe1af-2.asc
new file mode 100644
index 0000000..8547463
--- /dev/null
+++ b/tests/openpgp/samplekeys/dda252ebb8ebe1af-2.asc
@@ -0,0 +1,29 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+
+mQINBFKD+38BEADSv5l4xOx9hCRJVcybq6yK5hTpGSFf3xo1bkhoMvyC62ehb4jD
+MDLwwNRyzCBEWQJLbq/LLizPFN2qXFJpXJcsuqsHNYRtDqDBEjtriRQwSqHnqTXt
+c0K46FYHldCJQ4/tBXxPI+WwtXjcNRWaV7n2BvR/Jk+B5e4Zz3LPnN0C4w5vORHs
+hN1jil8A3Hs/F+OmlQYrU8ZtNwTpSo2EXxe2fVgSDCsKRyNsPZj++OyujPzW+yaN
+lJ9I/q6s9gvX9o9o7nwZbqBETipWsdRK6RfBdTKpnyLNordbWwWTk6GxN8T5Ppit
+P6a3UlQ71VuflcswCTmEQ1pEfZrlRFKa9psBOW+cZLNxT9h0jGFMh6/B3w48Sag+
+cFcPBFWParC+cAXBIURDxT9G6bzNLogg7YKoaPsyiXnLDH2VJUCXs27D2wPJL24Q
+S7npvsg63MPPssWgG5cauLznmNR4y5pQi6oH/C10v0zrUJy6FPJzQhYRhWOvhtz6
+j88RGMrFNNCdB2VACtn699D+ixu3nRlXHIKCT+xLSfgslVYifmJOCNljBLGHOQ1e
+FJxQuNVpmmxjvk/8kqK+pHLB9Qn6M1ZYzip7OyUL3OAWabCabgEw2bQmUhiBWD3u
+buv0WAVOJEAFvBCAeYNQzrQMY+Rc3RnvynG4pI6Tbo8wC6/IJcDOw516JwARASB3
+tChBNTUxMjA0MjczNzRGM0Y3QUE1RjExNjZEREEyNTJFQkI4RUJFMUFGiQI3BBMB
+CgAhBQJSg/uTAhsDBQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAAAoJEN2iUuu46+Gv
+9L0P/3tFu0LOZ/dAPjUNfKJCZqcIuVnD5xShMTsUbVx+QoXMy7rt4iRLD7ofGi/I
+vTAZehxk3sk/Slx5nbews+3NItyw6mcaP9HlmwKNr6k7BC2kJHcCxH4DNzhmIx1H
+3T/CggtHX42JBYKlGf22y+M8jAbvsPOUfTznx96mYNrOY6s1dJyn0kRleqJ8+tGj
+/5+0y90iZnGCa0FtacQkKUPkXwVodeZVxk8z5OEipShYKc+8dl+5WsvOzHqLC/KY
+xCGRb4JaqEMwouLNg8dTNAXXUvFGqJNDX4+andggogmI1hdD9xExfSU9cAGegg2t
+vvveC4S+CCHd+zt88iK5ze6F61RxwYhhNbkuFGjdgNGCpHtG/BQhKnYJuKEbq3oi
+mgNyxJERlfgaWXveiMG0AmACXN+jCkTtqZjQnsg2N2QDL3tjY7usmuiwRL1aVOFG
+Kw5/Cc+2nDeANS3Xi1403Ni269b1c6kNSoLe4zd0WsbO3Kouds8F8EQfeheXQe97
+ZxuvBOMsR9wHC3f0sl/vfxCGdUC+khmKk5taKnUeUFJmVmh5ghlVy8FySHGB0QHO
+zd8GUl59rFpQJNpNFQW2YKDhrcjxIr2AeJrdoDI6NsQ02+Qtep/bbq53hqtAD4jF
+t3S8vBbTXtRk6g2qn4ojF4SOIc8SAiZcURgVFuSJX8ngFbO4
+=OEw/
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/e2e-p256-1-clr.asc b/tests/openpgp/samplekeys/e2e-p256-1-clr.asc
new file mode 100644
index 0000000..2b53091
--- /dev/null
+++ b/tests/openpgp/samplekeys/e2e-p256-1-clr.asc
@@ -0,0 +1,37 @@
+pub nistp256/03288C74F8BE8F0F 1970-01-01
+uid [ unknown] <example@another.test>
+sub nistp256/A6ED196C7C513F1E 1970-01-01
+
+Not protected.
+
+Taken from
+https://github.com/google/end-to-end/issues/326#issuecomment-123585977
+
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Charset: UTF-8
+Version: End-To-End v0.3.1342
+
+xf8AAAB3BAAAAAATCCqGSM49AwEHAgMEmUwnXtxBvQY+nXvduAbd626NmYshRVi4
+HULGQ9fAHjKqfld4qWk97o+ggZDAnhQJ/Jm3ljtXr3/SosXUsSh7AAABAP2/JEYo
+22A3Ju3N3vhcbSuvJiHggUDtaomAX2ts2uGYEOvN/wAAABY8ZXhhbXBsZUBhbm90
+aGVyLnRlc3Q+wv8AAACNBBATCAA//wAAAAWCVazty/8AAAACiwn/AAAACZADKIx0
++L6PD/8AAAAFlQgJCgv/AAAAA5YBAv8AAAACmwP/AAAAAp4BAACIEgD8C80DxHrk
+iIBDHF5EWguzM+gUTb4xmIdTAJ2wGUOnTOoA/RpWuJNKU3kdtnnmqce88//jN8VF
+1Ho0BONH1b7dRV4ix/8AAAB7BAAAAAASCCqGSM49AwEHAgMEyfb375CDU05C3BXj
+FY3tGbGEmGrTgNj0lAzdbi7TVm5tiHidcNWPHSQPS8aMmygH23OvIkTBmJdCHR38
+lGID/gMBCAcAAQD8IOp5uKaGHtkmHNdwiwizTl3a2fAltOEAmWwyS6X0qBD1wv8A
+AABtBBgTCAAf/wAAAAWCVazty/8AAAAJkAMojHT4vo8P/wAAAAKbDAAA88EBAKve
+TpskPN10clQ6TeCFqlq51jhB5ZhzPSq64ChB7p8nAQCa9aJZneQOvMDquN/1vpJK
+MvDHHXB+EgIsuAzL0DtfL8b/AAAAUgQAAAAAEwgqhkjOPQMBBwIDBJlMJ17cQb0G
+Pp173bgG3etujZmLIUVYuB1CxkPXwB4yqn5XeKlpPe6PoIGQwJ4UCfyZt5Y7V69/
+0qLF1LEoewDN/wAAABY8ZXhhbXBsZUBhbm90aGVyLnRlc3Q+wv8AAACNBBATCAA/
+/wAAAAWCVazty/8AAAACiwn/AAAACZADKIx0+L6PD/8AAAAFlQgJCgv/AAAAA5YB
+Av8AAAACmwP/AAAAAp4BAACIEgD8C80DxHrkiIBDHF5EWguzM+gUTb4xmIdTAJ2w
+GUOnTOoA/RpWuJNKU3kdtnnmqce88//jN8VF1Ho0BONH1b7dRV4izv8AAABWBAAA
+AAASCCqGSM49AwEHAgMEyfb375CDU05C3BXjFY3tGbGEmGrTgNj0lAzdbi7TVm5t
+iHidcNWPHSQPS8aMmygH23OvIkTBmJdCHR38lGID/gMBCAfC/wAAAG0EGBMIAB//
+AAAABYJVrO3L/wAAAAmQAyiMdPi+jw//AAAAApsMAADzwQD/ahaSqogMflSlGJRU
+Z6Qb51EAaYBB5nL/u1ckWLh/CCEBAM83CFzh1qJXzYnl5DJNAPnj4jJgJKtSxOhn
+bvlk62wx
+=Xjs9
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/e2e-p256-1-prt.asc b/tests/openpgp/samplekeys/e2e-p256-1-prt.asc
new file mode 100644
index 0000000..d30e8c0
--- /dev/null
+++ b/tests/openpgp/samplekeys/e2e-p256-1-prt.asc
@@ -0,0 +1,39 @@
+pub nistp256/03288C74F8BE8F0F 1970-01-01
+uid [ unknown] <example@another.test>
+sub nistp256/A6ED196C7C513F1E 1970-01-01
+
+Passphrase is "a".
+
+Taken from
+https://github.com/google/end-to-end/issues/326#issuecomment-123585977
+
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Charset: UTF-8
+Version: End-To-End v0.3.1342
+
+xf8AAAClBAAAAAATCCqGSM49AwEHAgMEmUwnXtxBvQY+nXvduAbd626NmYshRVi4
+HULGQ9fAHjKqfld4qWk97o+ggZDAnhQJ/Jm3ljtXr3/SosXUsSh7AP4JAwLJdqYd
+6K+4XWACOPArMgQfaUFtQY54pRS1Vo98N4Jpw7o0iYAr80y40s5DaBIcUD5UuMHM
+p5no4vv8/hVCkIWJvoD/08rIzJDYEc9h2S4Lzf8AAAAWPGV4YW1wbGVAYW5vdGhl
+ci50ZXN0PsL/AAAAjQQQEwgAP/8AAAAFglWs7cv/AAAAAosJ/wAAAAmQAyiMdPi+
+jw//AAAABZUICQoL/wAAAAOWAQL/AAAAApsD/wAAAAKeAQAAiBIA/AvNA8R65IiA
+QxxeRFoLszPoFE2+MZiHUwCdsBlDp0zqAP0aVriTSlN5HbZ55qnHvPP/4zfFRdR6
+NATjR9W+3UVeIsf/AAAAqQQAAAAAEggqhkjOPQMBBwIDBMn29++Qg1NOQtwV4xWN
+7RmxhJhq04DY9JQM3W4u01ZubYh4nXDVjx0kD0vGjJsoB9tzryJEwZiXQh0d/JRi
+A/4DAQgH/gkDAsplyBF6DNuBYC3tTyYEL0QQjWrcaaeTk4JSb93mog6QlL610EO5
++muowWT9Dl8Ll77BjQSpj7mmqGHIj/IxJubOYqa+iW1e4pj5qlXCaBbC/wAAAG0E
+GBMIAB//AAAABYJVrO3L/wAAAAmQAyiMdPi+jw//AAAAApsMAADzwQEAq95OmyQ8
+3XRyVDpN4IWqWrnWOEHlmHM9KrrgKEHunycBAJr1olmd5A68wOq43/W+kkoy8Mcd
+cH4SAiy4DMvQO18vxv8AAABSBAAAAAATCCqGSM49AwEHAgMEmUwnXtxBvQY+nXvd
+uAbd626NmYshRVi4HULGQ9fAHjKqfld4qWk97o+ggZDAnhQJ/Jm3ljtXr3/SosXU
+sSh7AM3/AAAAFjxleGFtcGxlQGFub3RoZXIudGVzdD7C/wAAAI0EEBMIAD//AAAA
+BYJVrO3L/wAAAAKLCf8AAAAJkAMojHT4vo8P/wAAAAWVCAkKC/8AAAADlgEC/wAA
+AAKbA/8AAAACngEAAIgSAPwLzQPEeuSIgEMcXkRaC7Mz6BRNvjGYh1MAnbAZQ6dM
+6gD9Gla4k0pTeR22eeapx7zz/+M3xUXUejQE40fVvt1FXiLO/wAAAFYEAAAAABII
+KoZIzj0DAQcCAwTJ9vfvkINTTkLcFeMVje0ZsYSYatOA2PSUDN1uLtNWbm2IeJ1w
+1Y8dJA9LxoybKAfbc68iRMGYl0IdHfyUYgP+AwEIB8L/AAAAbQQYEwgAH/8AAAAF
+glWs7cv/AAAACZADKIx0+L6PD/8AAAACmwwAAPPBAP9qFpKqiAx+VKUYlFRnpBvn
+UQBpgEHmcv+7VyRYuH8IIQEAzzcIXOHWolfNieXkMk0A+ePiMmAkq1LE6Gdu+WTr
+bDE=
+=Sgsj
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/ecc-sample-1-pub.asc b/tests/openpgp/samplekeys/ecc-sample-1-pub.asc
new file mode 100644
index 0000000..478fc3a
--- /dev/null
+++ b/tests/openpgp/samplekeys/ecc-sample-1-pub.asc
@@ -0,0 +1,22 @@
+The key has been generated by the first GnuPG ECC version at
+http://code.google.com/p/gnupg-ecc.
+
+The sample key has ECDSA top key 0xBAA59D9C and a single ECDH
+encryption subkey 0x4089AB73. ECDH subkey uses SHA-256 and AES-128
+with KDF.
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2.1.0-ecc (GNU/Linux)
+
+mFIETJPQrRMIKoZIzj0DAQcCAwQLx6e669XwjHTHe3HuROe7C1oYMXuZbaU5PjOs
+xSkyxtL2D00e/jWgufuNN4ftS+6XygEtB7j1g1vnCTVF1TLmtCRlY19kc2FfZGhf
+MjU2IDxvcGVucGdwQGJyYWluaHViLm9yZz6IegQTEwgAIgUCTJPQrQIbAwYLCQgH
+AwIGFQgCCQoLBBYCAwECHgECF4AACgkQC6Ut8LqlnZzmXQEAiKgiSzPSpUOJcX9d
+JtLJ5As98Alit2oFwzhxG7mSVmQA/RP67yOeoUtdsK6bwmRA95cwf9lBIusNjehx
+XDfpHj+/uFYETJPQrRIIKoZIzj0DAQcCAwR/cMCoGEzcrqXbILqP7Rfke977dE1X
+XsRJEwrzftreZYrn7jXSDoiXkRyfVkvjPZqUvB5cknsaoH/3UNLRHClxAwEIB4hh
+BBgTCAAJBQJMk9CtAhsMAAoJEAulLfC6pZ2c1yYBAOSUmaQ8rkgihnepbnpK7tNz
+3QEocsLEtsTCDUBGNYGyAQDclifYqsUChXlWKaw3md+yHJPcWZXzHt37c4q/MhIm
+oQ==
+=hMzp
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/ecc-sample-1-sec.asc b/tests/openpgp/samplekeys/ecc-sample-1-sec.asc
new file mode 100644
index 0000000..5ff5555
--- /dev/null
+++ b/tests/openpgp/samplekeys/ecc-sample-1-sec.asc
@@ -0,0 +1,25 @@
+The key has been generated by the first GnuPG ECC version at
+http://code.google.com/p/gnupg-ecc.
+
+The sample key has ECDSA top key 0xBAA59D9C and a single ECDH
+encryption subkey 0x4089AB73. ECDH subkey uses SHA-256 and AES-128
+with KDF. The password for the key is "ecc".
+
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v2.1.0-ecc (GNU/Linux)
+
+lJ0ETJPQrRMIKoZIzj0DAQcCAwQLx6e669XwjHTHe3HuROe7C1oYMXuZbaU5PjOs
+xSkyxtL2D00e/jWgufuNN4ftS+6XygEtB7j1g1vnCTVF1TLm/gMDAmHomSLb9NbE
+oyWUoqgKTbZzbFR/SWmiCcuiQEhREcTyvyU1hAglj7FsBJoQ6/pbeAEQZ3bVzlNM
+8F0nF8KPLPuEADF1+4CntCRlY19kc2FfZGhfMjU2IDxvcGVucGdwQGJyYWluaHVi
+Lm9yZz6IegQTEwgAIgUCTJPQrQIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
+CgkQC6Ut8LqlnZzmXQEAiKgiSzPSpUOJcX9dJtLJ5As98Alit2oFwzhxG7mSVmQA
+/RP67yOeoUtdsK6bwmRA95cwf9lBIusNjehxXDfpHj+/nKEETJPQrRIIKoZIzj0D
+AQcCAwR/cMCoGEzcrqXbILqP7Rfke977dE1XXsRJEwrzftreZYrn7jXSDoiXkRyf
+VkvjPZqUvB5cknsaoH/3UNLRHClxAwEIB/4DAwJh6Jki2/TWxKO7gHKWIcOcxYZp
+CRWjlUghbKb6Q83p8GLPjKRN0USl/U1tObWdksqMXhUO0ePLWUnrbwoWYfYXg9Er
+ADTgCYhhBBgTCAAJBQJMk9CtAhsMAAoJEAulLfC6pZ2c1yYA/3eJRirPQZmBno+Z
+P/HOBSFWmFt4cUBGUx3oqiUd5loOAP480pb+vXx9ipljJWCJDSl/boRSuqB4hePP
+qt9Rd5gNdQ==
+=O8Dg
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/ecc-sample-2-pub.asc b/tests/openpgp/samplekeys/ecc-sample-2-pub.asc
new file mode 100644
index 0000000..f898012
--- /dev/null
+++ b/tests/openpgp/samplekeys/ecc-sample-2-pub.asc
@@ -0,0 +1,25 @@
+ECC NIST P-384 key taken from
+https://sites.google.com/site/brainhub/pgpecckeys
+
+The sample key has ECDSA top key 0x098033880F54719F and a single ECDH
+encryption subkey 0xAA8B938F9A201946. ECDH subkey uses SHA-384 and
+AES-256 with KDF.
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: PGP Command Line v10.0.0 (Linux)
+
+mQBvBE1TBZITBSuBBAAiAwME9rjFrO1bhO+fSiCdsuSp37cNKMuMEOzVdnSp+lpn
+OJlCti1eUTZ99Me/0/jlAP7s8H7SZaYhqOu75T6UfseMZ366FDvRUzwrNQ4cKfgj
+E+HhEI66Bjvh5ksQ5pUOeZwttCRlY19kc2FfZGhfMzg0IDxvcGVucGdwQGJyYWlu
+aHViLm9yZz6JAMsEEBMJAFMFAk1TBZIwFIAAAAAAIAAHcHJlZmVycmVkLWVtYWls
+LWVuY29kaW5nQHBncC5jb21wZ3BtaW1lBAsJCAcCGQEFGwMAAAACFgIFHgEAAAAE
+FQkKCAAKCRAJgDOID1Rxn8orAYCqNzUJaL1fEVr9jOe8exA4IhUtv/BtCvzag1Mp
+UQkFuYy0abogj6q4fHQSt5nntjMBf1g2TqSA6KGj8lOgxfIsRG6L6an85iEBNu4w
+gRq71JE53ii1vfjcNtBq50hXnp/1A7kAcwRNUwWSEgUrgQQAIgMDBC+qhAJKILZz
+XEiX76W/tBv4W37v6rXKDLn/yOoEpGrLJVNKV3aU+eJTQKSrUiOp3R7aUwyKouZx
+jbENfmclWMdzb+CTaepXOaKjVUvxbUH6pQVi8RxtObvV3/trmp7JGAMBCQmJAIQE
+GBMJAAwFAk1TBZIFGwwAAAAACgkQCYAziA9UcZ+AlwGA7uem2PzuQe5PkonfF/m8
++dlV3KJcWDuUM286Ky1Jhtxc9Be40tyG90Gp4abSNsDjAX0cdldUWKDPuTroorJ0
+/MZc7s16ke7INla6EyGZafBpRbSMVr0EFSw6BVPF8vS9Emc=
+=I76R
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/ecc-sample-2-sec.asc b/tests/openpgp/samplekeys/ecc-sample-2-sec.asc
new file mode 100644
index 0000000..b163f63
--- /dev/null
+++ b/tests/openpgp/samplekeys/ecc-sample-2-sec.asc
@@ -0,0 +1,22 @@
+ECC NIST P-384 key taken from
+https://sites.google.com/site/brainhub/pgpecckeys
+
+The sample key has ECDSA top key 0x098033880F54719F and a single ECDH
+encryption subkey 0xAA8B938F9A201946. ECDH subkey uses SHA-384 and
+AES-256 with KDF. The password for the key is "ecc".
+
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: PGP Command Line v10.0.0 (Linux)
+
+lQDSBE1TBZITBSuBBAAiAwME9rjFrO1bhO+fSiCdsuSp37cNKMuMEOzVdnSp+lpn
+OJlCti1eUTZ99Me/0/jlAP7s8H7SZaYhqOu75T6UfseMZ366FDvRUzwrNQ4cKfgj
+E+HhEI66Bjvh5ksQ5pUOeZwt/gcDAkrFTsfF6LKsqD/tW6Eot2DDE8znJjnQQ/Nr
+H98XT1WQ9V0ED8l9DDIIj7z80ED3NR8XMSI8Ew/A/0w6NDPL978BX0MGvpaeBaWV
+tEuH1EPAxiA+hFALwftY+a8s1zLktCRlY19kc2FfZGhfMzg0IDxvcGVucGdwQGJy
+YWluaHViLm9yZz6dANYETVMFkhIFK4EEACIDAwQvqoQCSiC2c1xIl++lv7Qb+Ft+
+7+q1ygy5/8jqBKRqyyVTSld2lPniU0Ckq1Ijqd0e2lMMiqLmcY2xDX5nJVjHc2/g
+k2nqVzmio1VL8W1B+qUFYvEcbTm71d/7a5qeyRgDAQkJ/gkDAqqmkngPLoJGqI4O
+rHyyU3wrrPzDDDURkseoUEZlDZINjyto26A8N825mqLqeFytJuuABYH1UnLs4d2x
+ZJZIYjEoFMPcFPuUtx+IZnECa1Vcyq2aRFCixVO0G/xrSFar
+=a4k3
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/ecc-sample-3-pub.asc b/tests/openpgp/samplekeys/ecc-sample-3-pub.asc
new file mode 100644
index 0000000..14b49d3
--- /dev/null
+++ b/tests/openpgp/samplekeys/ecc-sample-3-pub.asc
@@ -0,0 +1,28 @@
+ECC NIST P-521 key taken from
+https://sites.google.com/site/brainhub/pgpecckeys
+
+The sample key has ECDSA top key 0x6B4184E145AF2FFE and a single ECDH
+encryption subkey 0x07EAAA48A81C4838. ECDH subkey uses SHA-512 and
+AES-256 with KDF.
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: PGP Command Line v10.0.0 (Linux)
+
+mQCTBE1TFQITBSuBBAAjBCMEAWuwULfE2XoQmJhSQZ8rT5Ecr/kooudn4043gXHy
+NZEdTeFfY2G7kwEaxj8TXfd1U1b4PkEoqhzKxhz/MHK/lwi2ARzW1XQiJ1/kFPsv
+IUnQI1CUS099WKKQhD8JMPPyje1dKfjFjm2gzyF3TOMX1Cyy8wFyF0MiHVgB3ezb
+w7C6jY+3tCRlY19kc2FfZGhfNTIxIDxvcGVucGdwQGJyYWluaHViLm9yZz6JAO0E
+EBMKAFMFAk1TFQIwFIAAAAAAIAAHcHJlZmVycmVkLWVtYWlsLWVuY29kaW5nQHBn
+cC5jb21wZ3BtaW1lBAsJCAcCGQEFGwMAAAACFgIFHgEAAAAEFQoJCAAKCRBrQYTh
+Ra8v/sm3Agjl0YO73iEpu1z1wGtlUnACi21ti2PJNGlyi84yvDQED0+mxhhTRQYz
+3ESaS1s/+4psP4aH0jeVQhce15a9RqfX+AIHam7i8K/tiKFweEjpyMCB594zLzY6
+lWbUf1/1a+tNv3B6yuIwFB1LY1B4HNrze5DUnngEOkmQf2esw/4nQGB87Rm5AJcE
+TVMVAhIFK4EEACMEIwQBsRFES0RLIOcCyO18cq2GaphSGXqZtyvtHQt7PKmVNrSw
+UuxNClntOe8/DLdq5mYDwNsbT8vi08PyQgiNsdJkcIgAlAayAGB556GKHEmP1JC7
+lCUxRi/2ecJS0bf6iTTqTqZWEFhYs2aXESwFFt3V4mga/OyTGXOpnauHZ22pVLCz
+6kADAQoJiQCoBBgTCgAMBQJNUxUCBRsMAAAAAAoJEGtBhOFFry/++p0CCQFJgUCn
+kiTKCNfP8Q/MO2BCp1QyESk53GJlCgIBAoa7U6X2fQxe2+OU+PNCjicJmZiSrV6x
+6nYfGJ5Jx753sqJWtwIJAc9ZxCQhj4V52FmbPYexZPPneIdeCDjtowD6KUZxiS0K
+eD8EzdmeJQWBQsnPtJC/JJL4zz6JyYMXf4jIb5JyGNQC
+=5yaB
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/ecc-sample-3-sec.asc b/tests/openpgp/samplekeys/ecc-sample-3-sec.asc
new file mode 100644
index 0000000..6552e7a
--- /dev/null
+++ b/tests/openpgp/samplekeys/ecc-sample-3-sec.asc
@@ -0,0 +1,24 @@
+ECC NIST P-521 key taken from
+https://sites.google.com/site/brainhub/pgpecckeys
+
+The sample key has ECDSA top key 0x6B4184E145AF2FFE and a single ECDH
+encryption subkey 0x07EAAA48A81C4838. ECDH subkey uses SHA-512 and
+AES-256 with KDF. The password for the key is "ecc".
+
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: PGP Command Line v10.0.0 (Linux)
+
+lQEIBE1TFQITBSuBBAAjBCMEAWuwULfE2XoQmJhSQZ8rT5Ecr/kooudn4043gXHy
+NZEdTeFfY2G7kwEaxj8TXfd1U1b4PkEoqhzKxhz/MHK/lwi2ARzW1XQiJ1/kFPsv
+IUnQI1CUS099WKKQhD8JMPPyje1dKfjFjm2gzyF3TOMX1Cyy8wFyF0MiHVgB3ezb
+w7C6jY+3/gcDAv+CotECRPpSqGkqKrz+xAhAqswHXzFIBprFF0XiDooWktZSTAUR
+JVB2U6m28wC4rE3RkqFeR1B+kg4nxEAJ9k6BI8oDE0iyOY5aklF2TxPpTs/BA+N2
+O4hnXb1l5qXfuyd3bSwDeyfq3CdFe4TeKp7vtCRlY19kc2FfZGhfNTIxIDxvcGVu
+cGdwQGJyYWluaHViLm9yZz6dAQwETVMVAhIFK4EEACMEIwQBsRFES0RLIOcCyO18
+cq2GaphSGXqZtyvtHQt7PKmVNrSwUuxNClntOe8/DLdq5mYDwNsbT8vi08PyQgiN
+sdJkcIgAlAayAGB556GKHEmP1JC7lCUxRi/2ecJS0bf6iTTqTqZWEFhYs2aXESwF
+Ft3V4mga/OyTGXOpnauHZ22pVLCz6kADAQoJ/gkDAki71k/zBW2qqGyScDNNuWaA
+9A5aWhpNNyRrFembt7f/W+b591G3twdNmdCIh29VoOmQw3fO8wwgsPTUxQFgd8J3
+ncft0zciEcDZi/ztLZA3+rIIP2myZLIs9xLG+k+gf3nXpeED4uYqQX3GL+32PKwg
+=Qnd8
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/ed25519-cv25519-sample-1.asc b/tests/openpgp/samplekeys/ed25519-cv25519-sample-1.asc
new file mode 100644
index 0000000..54d2044
--- /dev/null
+++ b/tests/openpgp/samplekeys/ed25519-cv25519-sample-1.asc
@@ -0,0 +1,21 @@
+pub ed25519 2016-06-22 [SC]
+ B21DEAB4F875FB3DA42F1D1D139563682A020D0A
+ Keygrip = 1E28F20E41B54C2D1234D896096495FF57E08D18
+uid [ unknown] patrice.lumumba@example.net
+sub cv25519 2016-06-22 [E]
+ 8D0221D9B2877A741D69AC4E9185878E4FCD74C0
+ Keygrip = EB33B687EB8581AB64D04852A54453E85F3DF62D
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2
+
+mDMEV2o9XRYJKwYBBAHaRw8BAQdAZ8zkuQDL9x7rcvvoo6s3iEF1j88Dknd9nZhL
+nTEoBRm0G3BhdHJpY2UubHVtdW1iYUBleGFtcGxlLm5ldIh5BBMWCAAhBQJXaj1d
+AhsDBQsJCAcCBhUICQoLAgQWAgMBAh4BAheAAAoJEBOVY2gqAg0KmQ0BAMUNzAlT
+OzG7tolSI92lhePi5VqutdqTEQTyYYWi1aEsAP0YfiuosNggTc0oRTSz46S3i0Qj
+AlpXwfU00888yIreDbg4BFdqPY0SCisGAQQBl1UBBQEBB0AWeeZlz31O4qTmIKr3
+CZhlRUXZFxc3YKyoCXyIZBBRawMBCAeIYQQYFggACQUCV2o9jQIbDAAKCRATlWNo
+KgINCsuFAP9BplWl813pi779V8OMsRGs/ynyihnOESft/H8qlM8PDQEAqIUPpIty
+OX/OBFy2RIlIi7J1bTp9RzcbzQ/4Fk4hWQQ=
+=qRfF
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/eddsa-sample-1-pub.asc b/tests/openpgp/samplekeys/eddsa-sample-1-pub.asc
new file mode 100644
index 0000000..5a65453
--- /dev/null
+++ b/tests/openpgp/samplekeys/eddsa-sample-1-pub.asc
@@ -0,0 +1,15 @@
+pub ed25519/97965A9A 2014-08-19
+ Key fingerprint = C959 BDBA FA32 A2F8 9A15 3B67 8CFD E121 9796 5A9A
+ Keygrip = 0DD40284FF992CD24DC4AAC367037E066FCEE26A
+uid [ unknown] EdDSA sample key 1 (draft-koch-eddsa-for-openpgp-00)
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2
+
+mDMEU/NfCxYJKwYBBAHaRw8BAQdAPwmJlL3ZFu1AUxl5NOSofIBzOhKA1i+AEJku
+Q+47JAa0NEVkRFNBIHNhbXBsZSBrZXkgMSAoZHJhZnQta29jaC1lZGRzYS1mb3It
+b3BlbnBncC0wMCmIeQQTFggAIQUCU/NfCwIbAwULCQgHAgYVCAkKCwIEFgIDAQIe
+AQIXgAAKCRCM/eEhl5ZamnNOAP9pKn5wz3jPsgy9p65zxz1+xJEr/cczFQx/tYkk
+49tkeAD+P9jJE4SFD2lVofxn1e22H7YLvcVyHDOA9gpYWTNXiAU=
+=Jbi7
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/eddsa-sample-1-sec.asc b/tests/openpgp/samplekeys/eddsa-sample-1-sec.asc
new file mode 100644
index 0000000..4b5fbcc
--- /dev/null
+++ b/tests/openpgp/samplekeys/eddsa-sample-1-sec.asc
@@ -0,0 +1,19 @@
+sec ed25519/97965A9A 2014-08-19
+ Key fingerprint = C959 BDBA FA32 A2F8 9A15 3B67 8CFD E121 9796 5A9A
+ Keygrip = 0DD40284FF992CD24DC4AAC367037E066FCEE26A
+uid [ unknown] EdDSA sample key 1 (draft-koch-eddsa-for-openpgp-00)
+
+The passphrase is "abc".
+
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v2
+
+lIYEU/NfCxYJKwYBBAHaRw8BAQdAPwmJlL3ZFu1AUxl5NOSofIBzOhKA1i+AEJku
+Q+47JAb+BwMCeZTNZ5R2udDknlhWE5VnJaHe+HFieLlfQA+nibymcJS5lTYL7NP+
+3CY63ylHwHoS7PuPLpdbEvROJ60u6+a/bSe86jRcJODR6rN2iG9v5LQ0RWREU0Eg
+c2FtcGxlIGtleSAxIChkcmFmdC1rb2NoLWVkZHNhLWZvci1vcGVucGdwLTAwKYh5
+BBMWCAAhBQJT818LAhsDBQsJCAcCBhUICQoLAgQWAgMBAh4BAheAAAoJEIz94SGX
+llqac04A/2kqfnDPeM+yDL2nrnPHPX7EkSv9xzMVDH+1iSTj22R4AP4/2MkThIUP
+aVWh/GfV7bYftgu9xXIcM4D2ClhZM1eIBQ==
+=+9EF
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/issue2346.gpg b/tests/openpgp/samplekeys/issue2346.gpg
new file mode 100644
index 0000000..cc2d5a8
--- /dev/null
+++ b/tests/openpgp/samplekeys/issue2346.gpg
@@ -0,0 +1,57 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v2
+
+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
+=njf7
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/rsa-rsa-sample-1.asc b/tests/openpgp/samplekeys/rsa-rsa-sample-1.asc
new file mode 100644
index 0000000..382d4e6
--- /dev/null
+++ b/tests/openpgp/samplekeys/rsa-rsa-sample-1.asc
@@ -0,0 +1,38 @@
+pub rsa2048 2016-06-22 [SC]
+ 5B83120DB1E3A65AE5A8DCF6AA43F1DCC7FED1B7
+ Keygrip = C6A6390E9388CDBAD71EAEA698233FE5E04F001E
+uid [ unknown] steve.biko@example.net
+sub rsa2048 2016-06-22 [E]
+ 4CB4D8C018C57E60EB3847901D777619BE310D79
+ Keygrip = D69102E0F5AC6B6DB8E4D16DA8E18CF46D88CAE3
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2
+
+mQENBFdqP+gBCACoG81sddF9ZZx6TsN7lenDxs53wqJt1bawToXZl6qJ+hO8tMNy
+/aUgaqqi8pC5FX3HlSRQhjRFDQXq4jR3+jecFK3wfwmxTKXMKhN52zhSIWClED47
+56B3wPITuwAG2WYFccClhrtWX8j+wBK5IpLVVAXQnORZLOP7fzUZkO1KDu3bP4D6
+f1LQyatIzgS08dnlp6WvsJDrkUeGY6R5smpx9f+PqBVfUVpmckbMOR+BYPJtplZT
+0lez4qWsmdWbqU7ZhdvnhMGcTbBbk9WbfR1IJptigeuK8vTU24Jp2FQj6iIBV9OD
+jUfr11EJ6W3TvHaWuddd0hfX9DnyH9rghrDFABEBAAG0FnN0ZXZlLmJpa29AZXhh
+bXBsZS5uZXSJATcEEwEIACEFAldqP+gCGwMFCwkIBwIGFQgJCgsCBBYCAwECHgEC
+F4AACgkQqkPx3Mf+0bd5kggAphS7UDycKadfaRH5JENmKXeI+UUd+E0iERwv7eXq
+RcgjNK1oHQSXN+ejDEXzZv2fcCRB7rWEvEXL0pCtPveyzDAQJdhZTRVgmfCXTr1m
+9pJfVC3B20jgx6ZxZO8jKDL+bqvufWJczWDT0iHP0Jv04SqASLRs2JRPy+a+w3GJ
++DzG8orfAKiIE1Qycovr8Ol+jdo9ZV9blRA8/j4eqZYg4b7AOf8/mDyXsx3xzSPV
+uwkDSluhaOrsV8N0suZ51rfdpapv6VJsXlyQbceJwwgSt2A1n2Sw3ZINwpO7BODy
+wO6J44751+qY4cmap4NItyqGQTT6TUEL9ANfrZFmPWmFWLkBDQRXaj/oAQgA255C
+UJxFEKLVwEoSgwZqXd94AhjGUbMY6NXdFj5cCq0JmWZrbpT/5OblTrymiH1iLmI0
+ymo+/s8vh6NtB98dhr1syH3asNQfXZRfF+u5X5hLDNPF4sUelsl4+EUef0Hbc9U+
+e+8F8A9TMxELSqQ8Ul3Hu42hc+/ugkc1G/8++Sv/f60TqWcUR2GmuiAvkuS1WmdA
+TMhwPr7vMfssV0X0mboz32//b/UfuOyctso5FM+bRaKrEJDQ2WDg57yqnaqsKEga
+jW0jElpAVIn792W6YWKOk4auYSpO5f7BVs40Z+bxKGxiH87z9fnmlYAsQwPOOxZw
+WaCSrReeheK6c6emAQARAQABiQEfBBgBCAAJBQJXaj/oAhsMAAoJEKpD8dzH/tG3
+baoH/0KI3pIUiIYiLESGXqF+s/W2BmGNwdkYldcyFwkXz84VXoG0B3k7nrwT2DOJ
+AEeToavzd3J+aZ4PmxBRAMtDhah0wsMXrwCI8y9Stmm6PIssnu9IP9+jgr4IkKIR
+UB/Wn6nzgseaNd7vN4JChCyLSvF+vLd3D56Wzq+hBjybaE+zcEusVLdKYDm2i0YC
+pkBkmSuC18lLxhNC8oSCCvVOiyw+TqGHhLnrpA4nGi0MLjAR3OgJ5d/TclYgkLcp
+yOupg9GplQsAZUFfQPrY80SJuN9ijBp4xtA1U+WCGKh4ySv1+odpRjPX3eOGUFKZ
+sJRKpZupoGWfVN78wm1nPLBKTvM=
+=6N/A
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/silent-running.asc b/tests/openpgp/samplekeys/silent-running.asc
new file mode 100644
index 0000000..e7c6db3
--- /dev/null
+++ b/tests/openpgp/samplekeys/silent-running.asc
@@ -0,0 +1,120 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v2
+
+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
+=tU5z
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/ssh-dsa.key b/tests/openpgp/samplekeys/ssh-dsa.key
new file mode 100644
index 0000000..58707b3
--- /dev/null
+++ b/tests/openpgp/samplekeys/ssh-dsa.key
@@ -0,0 +1,12 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBvAIBAAKBgQCx0bAMKBKzYJugVtUFRRiF8jV4eT8mowj5C0q4QRPuPAGgPdqq
+g1PKmoIpCKLynqH29+BFErp1OOenWKRdu9claTu0lmIrMYeYw8liKsyMTg5/DxoV
+sRXD1DFoKdeZPDVUxOEQWsLf/IuuLXy4c9GxzET88wUDeieV+GcYQFADoQIVAKS7
+giO+VWOnwqr0p/csUWltpo8TAoGBAJcVpe9riXRuxJtmy1sbJJzOvtPtXk5MCpGs
+T/KEXJuVZvu334zkySDd9Is1ML2g5e81ONRCgCGHpwNOzoLC4+yp+pr1E+B2xkUY
+ouEtZWhKlbaYw7UdHiRRMEVJqvu+CdyI2gwOveDSrVhoXmGyz9PQVNoiuRXP2hMF
+C21jNnBrAoGBAILRAY0/mqsaOTII3uC8KvqwbKlmPnYMJr0COmU1PbOXvaeyWLqG
+NHhwPZg6OEhqEk+WMIwb2Dcv70AIYKQU8jX0elh0lk6pE8bomn7/ZIkqa60VG1Cx
+8x2GUNag78LvnLfmUPAXOrrCPfbGuqdogCymUz1qrtEzdOSbeBvCMAAFAhQr1sV4
++UWhlUoExLMDdIyT/ohfxQ==
+-----END DSA PRIVATE KEY-----
diff --git a/tests/openpgp/samplekeys/ssh-ecdsa.key b/tests/openpgp/samplekeys/ssh-ecdsa.key
new file mode 100644
index 0000000..db7c45c
--- /dev/null
+++ b/tests/openpgp/samplekeys/ssh-ecdsa.key
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIF8Mt42n5l2eJB2rk5TSnS98xAtR2VfmmI96WT5OtFrdoAoGCCqGSM49
+AwEHoUQDQgAEsphhghltvEj+1rFEcIlSNy2ze7IMHdhGsH060PwOzjKTy15M8zHI
+uaH9SOMXTzn3Bial8bxrXLsOYEhRZhYSrA==
+-----END EC PRIVATE KEY-----
diff --git a/tests/openpgp/samplekeys/ssh-ed25519.key b/tests/openpgp/samplekeys/ssh-ed25519.key
new file mode 100644
index 0000000..c3760b8
--- /dev/null
+++ b/tests/openpgp/samplekeys/ssh-ed25519.key
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACARyDcsgSrXAdihOuO5lN+qVKVPdwsXCmOZ61XYVUA1MAAAAJAOqdhVDqnY
+VQAAAAtzc2gtZWQyNTUxOQAAACARyDcsgSrXAdihOuO5lN+qVKVPdwsXCmOZ61XYVUA1MA
+AAAEATyEkvuhAExcEet+Rc2Qz2Fxg4iIi4XXJLpZFKwWsY3hHINyyBKtcB2KE647mU36pU
+pU93CxcKY5nrVdhVQDUwAAAACHRlc3Qga2V5AQIDBAU=
+-----END OPENSSH PRIVATE KEY-----
diff --git a/tests/openpgp/samplekeys/ssh-rsa.key b/tests/openpgp/samplekeys/ssh-rsa.key
new file mode 100644
index 0000000..ef0425c
--- /dev/null
+++ b/tests/openpgp/samplekeys/ssh-rsa.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpgIBAAKCAQEAxp4sIUtrNBl4Vbd4075CmtHmwxTc0FhQIGw36kptbrWReLb9
+Np0RQylKyc6qUruxZlCdPVFo7iX3vs272/0GEakPv0DAsKGbe1nTsMyxxz0o3dP4
+JQOlOGEnpETa0ybfPLMX1+qNiBdm7HLjqcP5+S0Exb0Z0deFNIhEP6XckUEgHmwA
+/AdDdUUKwwvZeZOi4XyBVt0vXzwM/+84ro27O+CZm9Du3qe1jTIsX7jUrqsUBhp9
+eUwa1jXfXuJJo9b4/GeP4S9x8U7ho+BQ6/HH03dzcKaY3FftanCZkcwxfGBBUiCK
+pIA5WgKimLcgP2R75Y3jilDoBh5HyIdGXo0aFwIDAQABAoIBAQCBXLIHeXS4eUJc
+KeSjnQ8KgV4Yf3UWqf5+L533lkRSUCYQhrbDpGeC49kXOejLe/4eUrEnJ+f8/HOx
+LZSGwvT5+bAM9CLMqGV5YNc1Fw1PZHFCkfXUPdyVrQnBvyr7Th0mDsuf0OAf3IYn
+yOipQMCGX6D1HaY8e3AB+CLjhab0X1vAwvqzPb/HIdtMhRWlJxzbuqnE3kr+Ccvz
+us3vmD4VBp0CF0f+yblcibMCHdHY6j8Ir6Qeq6Mbd6lEXRPW1TgUqP15idVaJ4AF
+1kGXDW9O0ycgrbopGZfk5yY60fEHGdr4QYjx2Gtx2xQcnPcjJ+j5kGgubKWxNhJE
+Qx7DPdYxAoGBAP29S+wD1df0U+Tr0x06N6M/nSjNacGs12Oq/ehNJHhTYUO9fWUl
+M2X/MXRMMMGsnGaLNsrLao9Jnq0ZU5GFICWYeVBvaCvRrGngbqJBy8jRv+QYyaQs
+AckLcdgLGvjhcXonHDcbcxpug7/qFwakT+KY2s11FrHBEzbAIuDiSSKfAoGBAMhj
+KPkrjWJh3xxpFrFnGYj5aF86ExrPe2LAP/8F6Ez7dQN+4bA6O5F4hpJ/X0q/6s0n
+IBljo/DgARCBjbwDSaAMEWdm8HDeBhJsSCdQHW38ylaRDi8CQDKR60N3a/tV1MRJ
+4fKoHZ+7HH3wc+Bjv3oDovwVyUMG7ekCjeqbqI2JAoGBAOkhYX5Jz9KJBAPSwLeb
+4760FfuFL+PooEVMt9kV96ouQbFxiqLB2UWfgJqv3iQ0Kcb1pbQRzag1Jfs4x9Vu
+ESk5vEyw729DSDxHHp8qAMhUHxC9zZZvcHx9bW3oVjHRQOfQw1XGfK0OWTKdK+bI
+VTWG55HaQK21DahCREmG31dVAoGBALBH80KHmsAioziGBi2YKjGCXtvu5eGfBsdP
+orzBQKOATmb91qLGB6MoaRI1NOo4POGu+qD7M7xyAt23aq0sIzfFhgX1260e1C6e
+zTawVsNsL7/JqbWXAEy8az+VrguTbTIkYL2sQStEWoM75WRPu6El09p5e+0YCnEC
+C0CJINUpAoGBAPF1fpPINHlUW+Bvo4Nj3935QgZI47yTplDusptyfYgFYXw6ZYel
+y5Zgv9TWZlmW9FDTp4XVgn5zQTEN1LdL7vNXWV9aOvfrqPk5ClBkxhndgq7j6MFs
+9+9V06HJDIsSrC0D/ajIkP+iT9Hd6eEZMkJ6y6XtTbkJGYt2zOtnrpb6
+-----END RSA PRIVATE KEY-----
diff --git a/tests/openpgp/samplekeys/whats-new-in-2.1.asc b/tests/openpgp/samplekeys/whats-new-in-2.1.asc
new file mode 100644
index 0000000..e16db85
--- /dev/null
+++ b/tests/openpgp/samplekeys/whats-new-in-2.1.asc
@@ -0,0 +1,128 @@
+These are the keys used in the whats-new-in-2.1 document. The private
+keys are in ../privkeys and protected with the passphrase "abc".
+
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2
+
+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
+PTgzPpanbg78WYNuT7+ZqlZYqj13
+=44AC
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/samplemsgs/clearsig-1-key-1.asc b/tests/openpgp/samplemsgs/clearsig-1-key-1.asc
new file mode 100644
index 0000000..4673c40
--- /dev/null
+++ b/tests/openpgp/samplemsgs/clearsig-1-key-1.asc
@@ -0,0 +1,17 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA256
+
+You are scrupulously honest, frank, and straightforward. Therefore you
+have few friends.
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v2
+
+iQE0BAEBCAAeBQJXakWmFxxzdGV2ZS5iaWtvQGV4YW1wbGUubmV0AAoJEKpD8dzH
+/tG3OiIH/18NlMSXXRFRrxXq9OZySzJxgLI7BjGilRTqb4ALeFzNjmCwu3Y+Gkdg
+t7NjYjSe0erWiKYDEmALICwcpmSmXHA//gol3QkHJKIlKQGXJP1qLvIde5+lnK8K
+YVwLKLBQBQtlGMkMXPdUEn9PgzSoBFoFIqrzQmAdLO3yijSdm0Mzl9wyIhtbUXk+
+VgX2d/6DRIwcKcFoX2QbFlM/z1kdrS6cOYFbJWavEpLDz9ON8Q8a8uqcBiqRlSpW
+eGOMMsysJs+44+qX6uE3hu2KJE9xvHwhSjJOxqtw8dN3KZ1+8IkxsDrvDAhn+Klf
+Hbtj647f/iTOF88o1ihO7goDi93Bpv4=
+=xAv4
+-----END PGP SIGNATURE-----
diff --git a/tests/openpgp/samplemsgs/clearsig-2-keys-1.asc b/tests/openpgp/samplemsgs/clearsig-2-keys-1.asc
new file mode 100644
index 0000000..0d7823e
--- /dev/null
+++ b/tests/openpgp/samplemsgs/clearsig-2-keys-1.asc
@@ -0,0 +1,20 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA256
+
+"The geeks shall inherit the earth."
+ -- Karl Lehenbauer
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v2
+
+iQE0BAEBCAAeBQJXakX/FxxzdGV2ZS5iaWtvQGV4YW1wbGUubmV0AAoJEKpD8dzH
+/tG3g1AH/iQakK5FoXpNQs6Nj9NR4NUwtIPmlLS/Tas21CDs1Lo1Fum1gjU0VUFN
+63+FTnbRg8nXfee9RPddLnec9lYWVqWSkggTFER8qQrj/EurltLMv/tHAZ+B0ueI
+mh2XkNHA6KXu3DFipAXQezWaUqi485TGTY6Qv9JtG/plOZBakcRTgCSAamyaDPBA
+PHgp85bPf5Zu4aFRBfmJp+IUH/EFLNFIHNXpYyZZy5ZdB3GuhAHGFp6tlpRFk4Z5
+vRU9BtdoeiIeoRHp4orMESGlbeZxUXG3CCrgzVk0e1pab0NrehwQ23+axMxFipya
+t6mi8Zrxpp7eFc9+ozp+7r4cH//uw8+IewQBFggAIwUCV2pF/xwccGF0cmljZS5s
+dW11bWJhQGV4YW1wbGUubmV0AAoJEBOVY2gqAg0Ko1YBAKVC98xZvGsNoaq0yDHG
+AJKmsvjnc8z3qmEHzGtxOQCiAP92ffXZr0EM4qNqbDR0EAws9qNo0XlDPcm0LDxy
+0JVcDw==
+=Ta4l
+-----END PGP SIGNATURE-----
diff --git a/tests/openpgp/samplemsgs/clearsig-2-keys-2.asc b/tests/openpgp/samplemsgs/clearsig-2-keys-2.asc
new file mode 100644
index 0000000..992f2ba
--- /dev/null
+++ b/tests/openpgp/samplemsgs/clearsig-2-keys-2.asc
@@ -0,0 +1,20 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA256
+
+The very remembrance of my former misfortune proves a new one to me.
+ -- Miguel de Cervantes
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v2
+
+iHsEARYIACMFAldqRlwcHHBhdHJpY2UubHVtdW1iYUBleGFtcGxlLm5ldAAKCRAT
+lWNoKgINCubRAQC0VyMKKFXWWxLOwCFO5ovhONxq2VLQ6c7jklZt0AAETgEA8ikc
+doPxIamOCta2QwgS0JHPhvgmL98GWM1dMLfD3gOJATQEAQEIAB4FAldqRlwXHHN0
+ZXZlLmJpa29AZXhhbXBsZS5uZXQACgkQqkPx3Mf+0beYKQgAp60uW2OmVAyaP2MC
+F6alWqWVkxw66L6QW6ciOpiuqjEoc9TN6pNIIP+MeSPu+SE71kw4nD0Vvu5mgH/2
+74dZMf7vFX3vERL/g8u7lTOv2GkXyKpFKAwvMxqPJ7zKUH9z6LxeBc2tNImjQ4mS
+7OL30n+SPrsY4FR3BS/d/EY2y+L9spi92oiJeXjgNHH7iIr5iWiSSXS7AwBla0zu
+r+mkX2Aats488CEfENACugg79q7cNLpUioeKdOHcqDxCS9wSpYK5Y2+IBqmFEv6t
+DKZ1iZnLlk6rHpkZ8aQi96PFbZVZPGnxsOFKkNPWwHjniKeJzoJwd7FqR5i2vrsJ
+UiWYwA==
+=gWAP
+-----END PGP SIGNATURE-----
diff --git a/tests/openpgp/samplemsgs/enc-1-key-1.asc b/tests/openpgp/samplemsgs/enc-1-key-1.asc
new file mode 100644
index 0000000..bd65330
--- /dev/null
+++ b/tests/openpgp/samplemsgs/enc-1-key-1.asc
@@ -0,0 +1,9 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+hF4DkYWHjk/NdMASAQdAPDV6Y3JTfAGDX8pfZcT6YggC7qV3g8B1ezijcfIcdVAw
++hCFGXS1EikBbZ21v79GtGh6Wp3fmyZFRQcsJZciLE/EFcbf9Mv4Q2qfRhKYHlqj
+0lwBRYQrwTJbMNspOwd2MidjYYUxb/02PNiqZSrWUeX0iPsgHFToJol9RVAqs4Zz
+bZNKL6y/GeRIRZY12Lzo2TIXSLfjvbMTdkoz53mMKiUXsi/fCKXkTmgIheni8w==
+=kmqY
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/samplemsgs/enc-1-key-2.asc b/tests/openpgp/samplemsgs/enc-1-key-2.asc
new file mode 100644
index 0000000..e9e6e70
--- /dev/null
+++ b/tests/openpgp/samplemsgs/enc-1-key-2.asc
@@ -0,0 +1,16 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+hQEMAx13dhm+MQ15AQf8DKnGFmadCHP3k8blxdRa73pC3BL0fn9YSp2+EvKP7n4Y
+KsVHmKSZ43RL2pq24y5CImLCu6gPkyFGzTn/vmxq8E2Ul8WOvyJiEuRTczNr5NNs
+rZiF7dRMSjeZXCEHme24XIXKGzbnlkALHxh83GpgxVmLqKIlHEjgXYn9fneH85M4
+KTBxIxpAhIKzninnGk2ikmAS2C6z370tRLYP+tQ6gcP8BbehCZFM+TRqyS3aXjdq
+WaV3OgY7uWzj4P0PBXBWx0V829tfgRF9Z70Zx+HA1BpOqvmOcsztah1Jq/pyAaeR
+7t2FunUZuUwbBIYg67/cxStYAXF9ih70tjSRfYBiotLAEAEvZfW1G7lMnfFCWxx8
+S8L+AD+BEdycI/kUZhgxFVde985CSYcpIcQZE4IuTYCoc96ZXsvil5Zlf5I//KDz
+toq+bxa+VU4Gr+h4lbcq8Sj8OPkx11/P4dOyydiYKLqEThig5l/h5IiROL8AvIMf
+TpNhu8TnECbjaEDaDt3RE3vIFP7ZV8zfpsibSFDaK9K0UhniSt/wF4NekBltUcBc
+kozlxWbvQ0k3A+xl1dBCBEpFaJrywRYFvz2sY5ISJS1X3ePJ4c9fsPXePTiy9a3W
+ItE=
+=rFeH
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/samplemsgs/enc-2-keys-1.asc b/tests/openpgp/samplemsgs/enc-2-keys-1.asc
new file mode 100644
index 0000000..abff596
--- /dev/null
+++ b/tests/openpgp/samplemsgs/enc-2-keys-1.asc
@@ -0,0 +1,17 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+hQEMAx13dhm+MQ15AQgAkI1KV+RVcuDJlzwXShDT9d2r+1GlV2r16z5vp0aDLETz
+Ga+OCTSiDR8So9xqM8kNKp12t2OrhmIerYu3dHQxZAWuqbhj/xkxfh0OyAP2wZb4
+MtwXIcRKWgUz5pUPYcp/7+Eo/dlBs1QaqxF8Lnh5jAlpxDeQvfSgjTZicZAS0rtY
+XONLWaX4nuuHb2DNrQWLDsMvDrwu8fJLPMNy7+tEzECs1G7Tv7D9xu/QHbGw6Zvk
+fxjWlLsD2nUQYwn/GpqitD02y7BHDoZKXIO8GccHdPhPOxZHLCiGIHQ7r61ResHA
+3SlqEsNF9OV81RaIg55ndM72ZLbDTC8ZQDIu/5cXaoReA5GFh45PzXTAEgEHQIFu
+PbA2WmzBGnzmBfXmRg8AVKE2JVvSYLjBynfTPbtKMAUbz9U2grH/0BdZPWaGuYUh
+HNPg9vmmzL5Ch3rSSunzhtxadesh/Gsic9ETkFz/d9K3AVzb9WEneFuEkk43lJAu
+X+btUyQ8rBhkmBQPorvZN+1i+NL0XOP3UJ0iIpo3bn/J7Dy9IEDojQAFtdOBuw6F
+hbWOMoRVodE5aA6JcRDR2HLj68X3TAou91a8krHJ8NAK84ilrZd07XEwGtNbaom5
+rZK9xNFIUV0Ddog6r5rJ/pqsN6o3iEYI2uhh0KYntbIHrRD05ZWRCXhQIGPb6qp8
+wEEydtbQpfJFRru8q7Y0V6MlzYflxI1H
+=m6X7
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/samplemsgs/enc-2-keys-2.asc b/tests/openpgp/samplemsgs/enc-2-keys-2.asc
new file mode 100644
index 0000000..ec6202c
--- /dev/null
+++ b/tests/openpgp/samplemsgs/enc-2-keys-2.asc
@@ -0,0 +1,16 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+hF4DkYWHjk/NdMASAQdALju99o8iXdJNYTuUNrk3ZgfLNvw4GuaLed/2PDLbLUEw
+LaFnwh5u4djUOPPtZHbNzmJimOobJxYg3gwDew3ERLBqweQqRcqFaypu9+Ss86Df
+hQEMAx13dhm+MQ15AQgAwHCbQ5TeyLGsrs+oC/dB7AZphqWwsSoVXTuxAi3NPbEF
+upvp3mu19HpBJFXijsjysaMbwUGB+DRVhMYwAANfnJJ2oxltNbhMeGic/vRsCjHx
+cJhjv/T0Jc3Yuh3YFlp4V3wMiTa7METMBL/2CQtT+MSQbBubkegcNPBkB5ss1civ
+WpQckerDKtv9ik0+gvYCgHw0wLyf7UmHRekiJigUats0IhEHoZYv/qa3kvcmJaKV
+WffHsOwxoS0jCwj15eV2YHQVJp7nnyxXlX9E7z4gzjxH4MbXpi+tVvBLGM8pHEg6
+EJ3U7koABqQ8446CnWC+OJKWO5cHoJjkOSCGALDoENKRAenz/t9qGzMWPInAx2iH
+lNg2brHS7UM8z53ESeqpYfaHS1QiMvtZWo8Wl9QPJa8vfrDw/bCtNALYU/OHw95N
+k9E+/JgWk9oQFc+syNHDJzw0qfEzblxzng5/d6W8vjggFkIrKwMwE1/6x1w6ZLoV
+MYG0TXjnLNBGzGCFRSoDx/RuzybgdDSySV/6OFfPAMSo1g==
+=iPxe
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/samplemsgs/enc-2-keys-hh-1.asc b/tests/openpgp/samplemsgs/enc-2-keys-hh-1.asc
new file mode 100644
index 0000000..87822ad
--- /dev/null
+++ b/tests/openpgp/samplemsgs/enc-2-keys-hh-1.asc
@@ -0,0 +1,20 @@
+This message has two anonymous recipients:
+
+ public key is 0000000000000000 (steve.biko@example.net)
+ public key is 0000000000000000 (patrice.lumumba@example.net)
+
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+hQEMAwAAAAAAAAAAAQf/YA9Ch/xoVYQmAEyo+9VqQxlvgYt23G/Vid3jgn0DFGp3
+DRyP8CVEn0ctGpb2kp8Cdgo+SMlO4WCIeVpYzZDCvHYwXSjh6EHMoLL/FVxyUh5q
+fXiyXl9692r+ms1qzfqJvVSSAjn4PzH31gFG6iQIz5E0yPRpbaDHA+7UlofP4Gfs
+AfidaVJuu9T7OIU50G554Lsjc3oXkr/m1OJDtNVABkkKLsC/bkVZKC6sTxFbmpXV
+mYJqq2cBFC5QSE1NO3Gcj4jVhP8CWE2hymIdFtk0HBGiDLQESw9OUmF/MHD6g2Fw
+NwVcH1pfzxXQYvygPPjaB0AiHR/52jsBifK/fG82R4ReAwAAAAAAAAAAEgEHQHTC
+vCgH7xW/vw5NRqRLSGarsauU9gY3x9aslz65kmYNMNmfnuedeyTxNj/X2C99/iYp
+BmofHiCYMkFjd5C0M/+mbGVQNdFwLG4WSSwXf3PkZtJoAXmj3A9opaFDmv51rs3a
+05IOjuHScOpUSKbTCWLY+rrAlrYSNQ0ZEvBdqFUXmoKIrUu/BLBPw654zrxTrFiX
+7cLcUlALJdQISuAEktJVb2E7dsrVFnLQsjJv+0EReH5FfSJRzqFaWjQ=
+=NW7s
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/samplemsgs/enc-2-keys-hr-1.asc b/tests/openpgp/samplemsgs/enc-2-keys-hr-1.asc
new file mode 100644
index 0000000..00d387a
--- /dev/null
+++ b/tests/openpgp/samplemsgs/enc-2-keys-hr-1.asc
@@ -0,0 +1,29 @@
+This message has one anonymous and one regular recipient:
+
+ public key is 0000000000000000 (steve.biko@example.net)
+ public key is 9185878E4FCD74C0 (patrice.lumumba@example.net)
+
+
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+hQEMAwAAAAAAAAAAAQf8Cipp2jtLlN1R/MucnvTxzDPLqRg2drOqWkGMoKuUlSvC
+OAzxliOgBLC9TfLxf/RP/v5KkRms1ovrXsm6bMuE59j04koJ1+K11IzO0jRSaFAI
+Ij5RM3z4v27dAR7leE1x5QKrltyScxNA74CAXXEvzm/kyGl+efLeeeZcOrbGMxSz
+vm2n9rc054bkqkIdJmqNkPlynD2Qo1oJUei0GAsV7s1IMB6dtqlGfSUJqmzYkNYt
+pIRd36xq60m74BrincO5xFNbvaSleA+nzLRUVig5KpEODJBGCpraVPQsQjoFzR1M
+CtjVVYUFo7s8QET87Wj7b07v06WpJ0e1Nt40zGqdtIReA5GFh45PzXTAEgEHQIA9
+Rwe1OkhWabVrw90AN5lmcTuruB2ANiW4pTiLVjpIMI1XNV9Ob1VysEUIqPIazZuF
+unlbIgU1sme+TVLV3/P07C7xiLEGUGUlfOjp4oiIqdLBBAEwtSO3m58GWZurA+aD
+K30EiHugSCdTYYdKQ6MbXNZxeLpCfslxzUAGwaXZDRemWrbTrBYXcC2+3Wz8R66S
+a9phYUlVSWCODZkvQvKARaxdvLdqZWRqRxFy3D1YYnYEvmb4thPUuxAiPb/2pTxJ
+j29hTuKDm3XJ5ZDDG1qlrPx71v1uBxUKBSZDd3YBPMxaLdia2fEmTYjnDN1Q6mzN
+NicMjmQo45ekA/QOeBobXMEPFsUr87LCY93PuPTDgQIen64ynOsWsVXv3kTM9X8b
+dmvj3MnKIWzDSIDXOKYvjnP4orCahHp/1qB/7obh2xoOS0qSMAphKaTnVhPAAQc5
+d5scPLWGe9GWKLpo7eh7yWrk04ryCbZNJOHjaKd2lwAbQ8ip9pA7dy387kUQsivh
+iOljf9oHPhRY8KrcIZzBJiyasGQMox0/wabQtnPHVqUDJdruaPsnqgU0P1Ojc17a
+b8cJYTk22pofDEs7oLcUeYZ8iTRpysSTCxydJwEmsj9n1lDW5M69KMlKLL0rZ0nv
+9nh2WbuwEnA71DzFq3V++dA6+geno5/yCyt/qROJ8I7zqC0DPiMfdpIfOBsC7n0W
+8hpDIps0
+=LChh
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/samplemsgs/enc-2-keys-rh-1.asc b/tests/openpgp/samplemsgs/enc-2-keys-rh-1.asc
new file mode 100644
index 0000000..1d864c3
--- /dev/null
+++ b/tests/openpgp/samplemsgs/enc-2-keys-rh-1.asc
@@ -0,0 +1,21 @@
+This message has one regular and one anonymous recipient:
+
+ public key is 1D777619BE310D79 (steve.biko@example.net)
+ public key is 0000000000000000 (patrice.lumumba@example.net)
+
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+hQEMAx13dhm+MQ15AQgAmDRRzNRfv/NXeJzBLOwcmBjWZ7UZAdr8Y5uqvOEdjIyj
+XQlvH56/lNVa4WsGcxRWfNucFs78pxqAY3YulApIs1o/+WheCpPEvxMJ5Z+s14rg
++jV0H+oW9UkeIVCKeLlHrosbUbYM8cvzsHdNFm1U6MnqH1DNiyTtwgzA065kyRDQ
+QwoCKf3Bsc+nmbfuWafdWDRwNptdE13JuRoFEd/KxhfXDhWF2r3ynM97erADTYMB
+RXzOAuNxLxrgdjJ2KJoJu6KRVGMJk1ermzeV1wv3bnfME+QRtZ2Gzu3heAktR9Bj
+gk4dOkEdYHQi7aYpoRaeWtK9An8FafLrEsbyYISNqoReAwAAAAAAAAAAEgEHQKD1
+Xk0mkgt/BPeRvR5giCsmMjniGdan99NWiiMJpcNNMOP65NimgxyOYDTbpsGl/tHY
+qmNzNy1Wk1/ZRRAr4+K8ITs5lmuoDeVVkGQTE2ahRtKEARtFMKoRDYO5dEgadlnL
+FdigDutyPLqVMaIwmx0HivjfXWEYyhBSXc0wwEvPhH76aBBOAnYZKKsLJVx+GoHp
+Lxlvdz6CsOOKfgxY7PBjCEpS4aOtIYNenW6fHMYBVTrOXpNok7Q18rx1yNOxvT3X
+g6zTetpqqM2SJKgSgRNsOobCDhqr
+=jW0C
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/samplemsgs/encsig-2-2-keys-3.asc b/tests/openpgp/samplemsgs/encsig-2-2-keys-3.asc
new file mode 100644
index 0000000..e563e8d
--- /dev/null
+++ b/tests/openpgp/samplemsgs/encsig-2-2-keys-3.asc
@@ -0,0 +1,35 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+hQEMAx13dhm+MQ15AQf7B8SvOp1oKADLmqzPCJp8kLUvt2oemNHYvSU06gTlTT8m
+DGJnA8a4S0+3q3Oqt/CObBX5tNr9KIB3OOgL8LujUffFVo2A6qfBWYnpyrDeJQOH
+idilyZvAu4CdovVvp+2DxAfBYNb0jinIjZEcF3YuIFqk1o5n9Jx0C3LDMgQwjKkb
+xEZeUkjt4i9Pb2JNP6+LQ8deDwLLcpS5ykP98MTHgG1OGw5QX1xxKArEq4YJXye3
+ubQBAifE3fGKswGiV5UuwrP3cB92KdtqYLCckrheDa96YJp7kZNDPFds4aqaD5i4
+Ps/bxXeZmeybhgxTT8Q1Ld7wUd+sFV36uRieHOMEIoReA5GFh45PzXTAEgEHQEyw
+MoBXgqtfF8+TdiUcIqeH+eXNOHjqGujt00BRn8JTMJNuCXoMZDmu45AaXZqiYxov
+TTfDyKGLVvaiTxEJdl/ty55X9C9ANppdFm3qZGZ6GdLqAQBRsaHHa5lSfUBrgJXC
+DLidkt1TA0u7owjuWRkUDlzBt3lEcgYEFd6c2zy3wxljpU0zB/gEmlEQiQAYB9dR
+alrnENgo93aExGoTW0LgsZlf1n8GuPCyK+3m+1+2ryr3qNreg69Y5HaW3aV4pEG/
+mMnxVffq0sJGtEQRAx8dESImO+jPVmdKx6JcGWQ4B3RmD3qzOgbGwRoeC+C/isV7
+t+VEC0iOlC+QyK7S1QgxcWwzl9ExSs1d+BM3cwNlwe2mLckgsayEUGXrafpifiTR
+w1CSyt25fb23iwOu1XZeHGnth/XAAJQcUsi02E+fpMPyS4S0v71PBn8By7iXHE8W
+stFZMP9Gcly6lh9qOFg108P+mIWOVj7xtCUMl0RRwxS2hrKypucJtPSmVZ6EgVok
+8j0tNm5nSjLzQ4A8I+O20Tx0sPBjmvH3IbMNCvjAQp6gXYlDgiHv2zxAgHwNJjRh
+ft1AJy/61HG3MtRNV1QP06l6tofGAzP4gBBqLJkVcK1bCGpx17LZ7t9GI573Y7Jr
+CIFN+CUWqzN64Q90IMDFwOl2ghQGZsIRh0jG3wOjd3C5cFo176BJiAq5WVelVEO8
+A3J/xMofeDdAVTkbpDpW+rE66I5dBwa8s9ej1zTpM0hmbiON+Ld9cCW3VPuDjjj3
+pAndSOcbfoq0Qd1RwshQVpfJJYjuhz9qCdlp392KWSvwTD/YuMIZ+nudgxk9Vbu/
+Z3ro/ggyH0FmnaJ53GnJ3NjsiJkSbQ21fSw0zJDNabpwdVPSzSvPtflh1qKiU60M
+eNI/QI6lKyZzwFCuAkcZKGWGQrDLjmbRtSMJHAw2cT1sQQJ5XtciiL+pOixawyNE
+pTnYI4f/983JewwweUwFJ5GkD/uY6hM10b4OKpjjm8rfpBVmW8rsuAGa5sSOAZB4
+xt+u6/dzVDCdQKtYV4pQHsHahAAkIGT1pWi0PMyWM3deo3sGaiCGcpM7qpO2qE4b
+paimL2Un0J1qPkr4cbykzzUx4U1zgHUHKDPhmSEtqLfPEd2DjUHsAvJZJFER4lD9
+yursATLzunEYiWUTuE6DKjcfQYPrAmat/mzquvf+oV5YgPvcY85U3t1XeyW9Zyip
+APYSJdgYdN8Wemh21vvGj8B7xnWMaJlcbsCbvuu2GALUGQKbhYzV02lMPSbEUHRH
+pRI8NviMcR4UD0/FK7g91I7yDqX6BLBckUw+W1KYKqVvlcMuDUOc5nQTxWXrPWJu
+o6EU4sD4bDaFOdDW8cuSBhxiifU+I+1s89p6+6M/Qwenh0hTvUsQwpUx/cXwjNXT
+0uRaIk/yjbEZj80lTKyAn1TvlJ4A2vYjscqfiiVYBU1/enfnsYgUf+TTK2qm3TtV
+HiuLLNvE2uy2IQfeZ3DnzZlMoCY8PA67yQCxJXR/hVX+/hzlZ0PoPylkYejs
+=yD/C
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/samplemsgs/encsig-2-2-keys-4.asc b/tests/openpgp/samplemsgs/encsig-2-2-keys-4.asc
new file mode 100644
index 0000000..1b63617
--- /dev/null
+++ b/tests/openpgp/samplemsgs/encsig-2-2-keys-4.asc
@@ -0,0 +1,33 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+hF4DkYWHjk/NdMASAQdAtNe4V9DKNR+N65wm9hJk8xRewYZPhmWADCcFraD0rnUw
+MWX9tj1E6GIKEhCAMomt/PoboZ8ncBJ4JZ/x4fltX5qsfIZkVqILolPAzrp5EbeE
+hQEMAx13dhm+MQ15AQgAkQn04BIdVZ6w0q13WfIoSepk2aQs39E6rmfZRUUs5Axk
+aTkHLQa3jSIpWXtSdrm5DBX0rhuNSiFk1h2pwc0OSnIhl6jxrjX1TN4dbXrtaJUz
+rguevhF72sfksr7p5sy/yFF1DBv3Z6MRKyyt4FjpbhzczDU0BD4cz0IGMb5tHLB0
+kTS1pJYtkajuWEGiyfT2dR1g0SdNoVwXiu+Hw+buPabAdjgVKocyGmdbYr/ip88t
+9o9AayTN2BH0z35YBwpdULcoM3Dww+sTcO2sG6xiy7E24t8RPFUQOfFm5vfmI8EH
+Zy4nId6ZkGEdkzX2UkU6FvX5vvru76My07nqKENDBdLpAXp08EPSUkTgnl9d7Hyq
+R1jMFiML3/QtMH7azdmjKdmkhrYPMgNoAiK1lO7pw3dU4eHfWDnPUWw8y/WHmoUT
+lxtZunT8GUh8ZxXl+skOqy2UXHPPRSN602oqma+yYKZrzn8hQm7Rq/tbmFPRTE7V
+cPCuRD0u3Rwnhldq//r5w6AgG1jKu0gXXzLYcubEl7S8fvXG/udSg1ASjhdhbYPD
+larTKCby1fESurfhwFnyaIGPknpzGooGFU7sIkrjilNPfVGv8CC10yMp7jOM7nXH
+hZ3w6JNHzB3UxlVjOjUkXFRxm3X4ydNXFgrp8soGyOnhjcUcN8A8gIXJoDQwB9G1
+STIilDwsBzFJOZfJSdy0/mjecvqT2slFsl3fjr0h0M2cTsYw1Ws5iG17HTJBVjpW
+frmWVjGVLRXkLGkumNbLpGxImlz2wlvuSlk/mqgrbRyyz6ifEpQc2o7uFvT6BGTp
+pG6qPafKLEAOkfOZGt/BKMsWESoOXlIa5B8B/4/t8me0Lni7RS09908ait1poKEM
+cDYNPtClQlBLJB3GLxPDDUT1WNcEBc+vScU317S5BRgDXBdao16DLzoIoh0C8kYu
+JBIQvXYLw23IBilHxzv0Fr/ta2joAUOnojNZMAaOawWj8i8/EwO2Hl0epx8Ww3ft
+VMnCF3nVuAIhjYEEzYI90dzA35lcSyEcBDXKBUAnOLi0LhwySi3rzM/d0yxdDGZH
+oPw2JQWpgCuv4OMin5YSRowUPhgFmltNc9I6qgVdy1vLKndC/OnCCtQj2OpUrYsH
+l1H3ADreaiunjtCrFTGYLey4EK6koLcb+qdKAOkRTaH28nRQGEyzZ4U93mbTsNmJ
+nAW4JCbZtMap9on9koJwiopEA+ONuktCD0j6RSAC+HdyhwN+MTWqCtTbO/tIvaqZ
+HtAlhiHk3GSi/qaox5dLKZqu5pa92OwiZrS6vS+dWTQpmyCyHYZcglsaRiHAGIEB
+3MVPKMvLgp5wV9uuSnr0aXaXoyEXjjMHbP8UnAxojnVxGJTOzsijE59ovddLgqUD
+81jYd4K3XIX+aWy3GicJaiAgzOYwJzBrOLZFGIlm9HkXKwM2gqd6TNjKQHxS63o0
+H6vXirtZmnRfA2SnmkGACbwTEa7vKARt4W45rXXk1GiQcxV0U7QrdQ9jMHIPtJF+
+py8jqdfjnNsUNM7PyTVjB9nTk9V3BkwIjUs46R6LqElZsAQQGcVo/EzBoPhjNUaf
+K+I=
+=kQLr
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/samplemsgs/encsig-2-keys-1.asc b/tests/openpgp/samplemsgs/encsig-2-keys-1.asc
new file mode 100644
index 0000000..649921e
--- /dev/null
+++ b/tests/openpgp/samplemsgs/encsig-2-keys-1.asc
@@ -0,0 +1,18 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+hQEMAx13dhm+MQ15AQgAiZPJa/zmtJ6cDpHVze6zBS+4OCbGeEpzcHBkpWiLKV91
+6CiwLTtL6Fhs7P/i5lEUzWQnRp0IGmUe8Ft5tugAL3ibv3Xm9PstXPZ2Q6EGzDCY
+98x1aQooSuiUwIB4uQ8zFqA2TYGNfRcDCGdHHLpWAps4F/QkZkQGEWmy7KQZetc+
+mLP6z04fQz5XemL0MaJcarLRE0OK8FI4+413DqQB3RyZsMFiFDAY46g3rA7xymuo
+Elum8PjMDXtAEpYAs2NHR29okFMinB7rR/DFGabQtzWIJPlgyGOFUVXs7YWj0Git
+SgEje73u8eEYAJYTpud1zup/KPUYOqJzyIMvOHDMz4ReA5GFh45PzXTAEgEHQGSH
+2coczePYstzayq418VjtNF+0ohoFKm8lrR9THREYMFJ4oA6/e7r3g38CWlb8kKxN
+butxPKCcO2OjZYU5PZMk03CwbpSWM0FTNJEzXfqdKtLAOgHgccG9wgBqAbcTejiX
+FQBBsLXRybq8Bra8qW+RVJ5noCav3TH06h8ZVXz/jJMLSUfKt8l+xRQDkYZ88cN3
+GhWNSc1eBOjS8e3JwGYaGs4vuoRVECbzee1DWNk3CUQOgeqZKLoSYHDRwHMpzP/N
+suXLpGTV7EoN4+qOcF5q/6cZV4gaGxgokoCUrM+IYfhOjmqK3lfo9/1GUxppyE+x
+XsWKiUMta3tJ6zhWYJPCZCqIZvzmkSfk3pNtOnsmmhF9gzwN8ehi/FHGFyHc8/gW
+qxx0KsCG7FO4Y514pdoa70KqA8QO63YjxTaFBH858yZr5ORlhzElwctgivU=
+=cWGf
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/samplemsgs/encsig-2-keys-2.asc b/tests/openpgp/samplemsgs/encsig-2-keys-2.asc
new file mode 100644
index 0000000..4eee21d
--- /dev/null
+++ b/tests/openpgp/samplemsgs/encsig-2-keys-2.asc
@@ -0,0 +1,18 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+hF4DkYWHjk/NdMASAQdA9op1WNWUj4E0PZ2h33tolomYTag75nRNg8qLo/2xfXcw
+QrekSuMoLtkv1KO6/tLIohqYYYdZL5cGadTxlBLyIEj32ISVj7El6DxJrmqKIK3y
+hQEMAx13dhm+MQ15AQgAnY6drrcce7MeloBIECLSbFIDjKOloUT4xtqspTg3GM1d
+wkXtTJOdEm1yLcNQsb+d8ZdZZfYZhotCyMlZ5QQtvf+0XOieb/FlitUI0twAMsj/
+kwjN9dop+KGLZadFoar5A8TBXUz25PfWmwEzz2qSmIPuoIUzhK90B3eGUG6foGzm
+1zEAawfyJ9w7XVAV6pNGJWG2LHSQr2POaMbZs/3iqxQl8p2yb25SlKrg3I35UClZ
+0FC9Hidw8bZ8/rZCyX9KYtHIENHzqT5+XEpaXwN4hBqwpVgUn6DcESv2BAR7KCHD
+ZwRRNVZtUvrftj05UIxAgnSAdK5GAyhLfWjCsH5Q3tLAPQGFdlgyYU9q+hWrrqwW
+1tAvUJQpSW97WyK1Aa9RJOLPNpfU1wzRGzzOuNuuqbL4l9OQktJ81Mihh4IWCXQD
+4mN7+nvltCm13bANdujRvZstGGFefRiwkBlEQq9uQMM2SVXA+JAff+AvD5F1Ofq8
+DPVMf/WDsKcoTTdqJahk/zoX4yFHprS50tO2z0Mb9souX14+AN+JJzAGQaGRlXXD
+TWeEkUXD18HcVzHfooqLUlYYr5zD2f2gNNVskPYH/iP3FGllvzBeQI1NCznAj+Zr
+AdOEXHKOkCJmj2RKnxXeOWTJSczoBlQgIQGd/yP/2TPsGesd4SbqFStYuefEZtw=
+=hq0A
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/samplemsgs/encsig-2-keys-3.asc b/tests/openpgp/samplemsgs/encsig-2-keys-3.asc
new file mode 100644
index 0000000..f10e92a
--- /dev/null
+++ b/tests/openpgp/samplemsgs/encsig-2-keys-3.asc
@@ -0,0 +1,23 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+hQEMAx13dhm+MQ15AQf+KX1A2pYF9HnvwZZU6kmiOKs6NL/d/8Y+kwfiLot5SnQW
+S/2JJm0b7ijyxBOoTyXu8UOqyaPa/eIJWeMqNANExkX83S1hoKfzgrBluzZR4sUB
+r6bZ5E26pn+gy+r1RvQJnxUWMX41ux+DSc+oqf36cZ5A4R1Ai6cD9jqW7vE0KINo
+jn6Od45NHNG16Q7igH9HgJiOXaibHFyiAfV5du0XB0HxpBlBKIBSV/4ewFUzxVy+
+oR4/3F7SkaUtGwcEi+PUEU26KuYz2ltYA9Ex/yTd59YcYbPTiiq+ynGRpOTgB0ti
+y7aYzJVOPWGCKn/TFy69QIoJZgcWTrmUJK39wxFNM4ReA5GFh45PzXTAEgEHQKqL
+epFBazPDtJvYGye9GW9gHMSjuTFuEm3yuo6kPIggMBRK/vWfTa7emGniukdA/8Bn
+hXrpSZUBab19RlT/mDhC8+CBE7MvEQMHsZvwsEWzt9LBAQFgEPLmrwSchnzw5+vN
+bcfeBye2n5STluKZ5IrW4XwZAvmp54w2OI/FDzf5dL1r+KCNiZpcmVO6IVVbEIeL
+eZj++YAPDS0cf/bPfWbyfvC/MLNM6IFICdkdlKQ30FC801Xv4OuXvgctjIkZBEDR
+CkDvkyrIEUtN9jJaAWjP3KopsCsxGtZ/ZPVU2yv8ekPRZ1paUIb370/NhEz9l2kK
+GwmqNm9g6/ekJwIF6kZKoEzncX7cpF0diSTHCyB/CsWc1ncWgn/nktZDsd7UicKP
+ypHScloUZfXDiQBcKV+0p6BxYib1MJOFrRbJTu+0Xu3KjcbecQ/mymgfDlkVUwXP
+QeGaQNUgQzO+iAW1hPH5Qf8eB8n2DlbqsFEWIXG7B3pGCI0eBWPeR/JpuCnIHMTh
+50YOwGqNQLjqRnl6hFi8amSIK5jRvRMzRWYO8TSZaYVh7uLh83cKkSV2e7d2pax6
+CqubZsoiaX71x+r3NaPYf+4hzAQUxPDZET2hTR4GOeEGT14t9RhqMPLTS+f9Ij7D
+/LbCpm6sc6eSmbKXZF/XAPpkBmnRIpgqJuA0TgNBnU7a0NEQP6nsicOpviH9SFEL
+waeu
+=6uha
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/samplemsgs/encsig-2-keys-4.asc b/tests/openpgp/samplemsgs/encsig-2-keys-4.asc
new file mode 100644
index 0000000..8937f5e
--- /dev/null
+++ b/tests/openpgp/samplemsgs/encsig-2-keys-4.asc
@@ -0,0 +1,23 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+hF4DkYWHjk/NdMASAQdAM+CNEu/KZIBKoKmvE96atl4CEdxThqamGsRt9IgeMxcw
+Te0hTUQf5LrrK9MhGymBcB2nCCy0bPtqVhA8TdZ6y3CH0QYMObkbSbIcVnGaVmGd
+hQEMAx13dhm+MQ15AQf9FcEbvw9ocsmqrteF2Cu6W2ChxrNy6ay0gcDwvd2QfbAE
+muM+OcKrvXhgDikOt3gAv4ES+2/ACzsqIZZJGUVWlrkSXYq9Uon+YX1zeK3BfmOK
+GvfLqc7p9x0YtrC8KEeMaqpd8z5bRhpF0ZPF4WbvZyiauDAa62FJiH/r4YngGLoY
+2hXFNZ2FFHa2EuobUfJUJwfA7VC13IdvqZ76bixrSSjxJjhntiswxYQI+OaXnEg8
+S/UwxR06GT7vOra1O9TGIHYwTcRGQT/3NHcIO3aJMRCHVP2dOLBMkFqkYf44kGeA
+e718nBN1UB7cfgv+n2bj7SYGdlEH0bmmpNTavEsDZdLBGQEcNlkdz3CqdqRhXUek
+hoWzCKTzOhIkoIhdyZd0stBlYJ54dT+9470JogkVqkNCWjAP1svI6LprOAR5b1sV
+m5ar5pCspumNRfMv6oDjXIsjCaux4zJfJV8XO38wmMn30eMPg1CzbKjhqMW+IfXe
+Tn8yxDBVGScIKkmaks6AE1v9WtfBSz+zT8sFe1ZFUMRcJ4+vohYmLVZXqkXGFJu7
+F3j8URhctnGb88h33y2+xglaqptso7XpM91OR17e6Vhh4dNAWB/GdKy4VviVY3W+
+fJ+zoimrPTFmPo2Ag+mveTsnTzmGdy4FHDDQCKE6QVcJPfVcfN0+yiPIOx/XacZR
+ZnQlI9Z+iYuN5yEchnVK65XZGQkdK+4/5Q/QGq7vLwaOHkMtItplIsretCGHAGEj
+XcCeHIY4pVZOd8Of8CSSPvtcaz4+FbZ/cfKXXf1zjdxg5BRkVvBAAtAYqquDUPJn
+qcG7tcUD6pQXVDHq+s0j8BofK9BXjjicrTI64RZw2RYntdbRSqd82offshvF4MJm
+72hIMbg5ExZsvdUa+IcRw49PoX/fEhKkmElZCI+5fsMG/NJuTfAtNjG5RbdgrYzQ
+eR6eIMr6BnY9ZZQRPbuv0te4di55B+HqmTry
+=/grx
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/samplemsgs/encz0-1-key-1.asc b/tests/openpgp/samplemsgs/encz0-1-key-1.asc
new file mode 100644
index 0000000..cf534db
--- /dev/null
+++ b/tests/openpgp/samplemsgs/encz0-1-key-1.asc
@@ -0,0 +1,12 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+hF4DkYWHjk/NdMASAQdAPo9H2rEUOisFYLfLQu91wGJCSIGs9jFiYwQsKlhsZlMw
+itRELU7+unvpPp8bIINqu4X6FP7hDzkZjOlQM/5JS0Z/q2jaWo4av8DCxYCK+yHU
+0sATAZtMvHD99HWEAis3GUlFBzf/jxPBmayNElVyifc5eH4d2pRfCqlZPx9gKX69
+OYymTKuUkkmzCgBxVfA7XPdIdqTmDbSjVwQ2LFeB8hQv6PsYFHY1vqs4xVmeotIu
+pgG1a40+6f8HC9YDNn2lUzktui/mi/VNqDwV9vOHYklGqpVDd81nHAl1wGkAzgBs
+8sYAcQjRAArAPKBaPTCtn6PZF4p4sDcabGImGR8cWwZHb9yxkHIomJRHUVTF1Uz4
+MUANuPQHpJE4eqKHUaE6wyTXyGEqJQ==
+=UB/1
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/samplemsgs/encz0-1-key-2.asc b/tests/openpgp/samplemsgs/encz0-1-key-2.asc
new file mode 100644
index 0000000..a885f5b
--- /dev/null
+++ b/tests/openpgp/samplemsgs/encz0-1-key-2.asc
@@ -0,0 +1,13 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+hQEMAx13dhm+MQ15AQf/WO25gVi//kxCs0RH+BbJ5OWRRkyZ5fD7mYUs6anJ/zRE
+SE/SKwNk4KsWi4ajRR7b7txj7HQN8l6RpjUFXDJwd0onkb5JoCcvVIdaSTRR8z3s
+5tkI/KTkPhlDPN+E5jCllUnJNSLoUwIIMw5Zgn0gRXxZeR6pUCB00+GmSPpoV+6X
+pEk8yuP5gcCFz2uiPmRl6QBezq6QLwlzYS6Kj+m2k2zqgEEgBc31aVnze8FTElbf
+Mm2wQ+w50PVaqHKkH7206PMIAd3Jsv2QP4XfgDDRxOe1/s6dHiCOfnhdrx/Fblp2
+VjluZFc/yL2YfofqqEWAxLLzh47aVN6JLr3bhdAVvNJEATedhlr+GTfhfI+KYO9r
+rZlP9aDHzvMKkqyX4WDD0O6a+698AnoseFVmrrBIsokdIt1RjLcpycE4BsCQOXHe
+EDBJtGo=
+=O1Fl
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/samplemsgs/issue2419.asc b/tests/openpgp/samplemsgs/issue2419.asc
new file mode 100644
index 0000000..b73efed
--- /dev/null
+++ b/tests/openpgp/samplemsgs/issue2419.asc
@@ -0,0 +1,7 @@
+-----BEGIN PGP ARMORED FILE-----
+Version: GnuPG v2
+Comment: Use "gpg --dearmor" for unpacking
+
+AA==
+=YWnT
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/samplemsgs/revoke-2D727CC768697734.asc b/tests/openpgp/samplemsgs/revoke-2D727CC768697734.asc
new file mode 100644
index 0000000..f20029c
--- /dev/null
+++ b/tests/openpgp/samplemsgs/revoke-2D727CC768697734.asc
@@ -0,0 +1,8 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Comment: This is a revocation certificate
+
+iGAEIBECACAWIQSg/0WQu2Ei7e9uPFQtcnzHaGl3NAUCWEaoMAIdAAAKCRAtcnzH
+aGl3NISuAJ9rsxoazHvPs89Ki33o/SgKMjOg/wCggbFG8V5wXU1njwuiviPUKap3
+uqA=
+=79yW
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/samplemsgs/sig-1-key-1.asc b/tests/openpgp/samplemsgs/sig-1-key-1.asc
new file mode 100644
index 0000000..875cf83
--- /dev/null
+++ b/tests/openpgp/samplemsgs/sig-1-key-1.asc
@@ -0,0 +1,8 @@
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v2
+
+iHsEABYIACMFAldqTEMcHHBhdHJpY2UubHVtdW1iYUBleGFtcGxlLm5ldAAKCRAT
+lWNoKgINCu0XAQC6VSdsGyTbvFPp5e6BmkmBzPcb5Kex4ar722k0jzhLzgD+Js2q
+Y1JIdjfW4GnFhdzqyUbuGTlk1wNY7Re1uNyD6gw=
+=c0oW
+-----END PGP SIGNATURE-----
diff --git a/tests/openpgp/samplemsgs/sig-1-key-2.asc b/tests/openpgp/samplemsgs/sig-1-key-2.asc
new file mode 100644
index 0000000..f7ae120
--- /dev/null
+++ b/tests/openpgp/samplemsgs/sig-1-key-2.asc
@@ -0,0 +1,12 @@
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v2
+
+iQE0BAABCAAeBQJXaky2FxxzdGV2ZS5iaWtvQGV4YW1wbGUubmV0AAoJEKpD8dzH
+/tG3LSUH+gJ++JOZuy5GfHwK+5GEGmeVbex4U9N84tYYAwZOsOpQsh4JxT44IH8S
+OG9OViY9xUaUmeSvVsuDR890RiZtKOXO3hCMwUo+HCDFLXgIXxosLlS55G1vfi8X
+NPl78Y9NFdtwtAkirpOT0oULJcbZ9NItkPjhoxZ16TlgG3GUE6lZzlZJLFAVCw7u
+6twOtPnq1AB4xB49rsIIW1XhCNrajwzBCghhl/PD4uM7ptSpGkZur5uOJ7nLjNEM
+Qo1mF+jQ6rjWA4OrvpmtW482yvNWejAS+JMlhNcP63hlBySjX3tFhGm8tWtUauCT
+3Ky7iF4dFFmhpIXUBT6mMmci4WdA3gE=
+=VdOj
+-----END PGP SIGNATURE-----
diff --git a/tests/openpgp/samplemsgs/sig-2-keys-1.asc b/tests/openpgp/samplemsgs/sig-2-keys-1.asc
new file mode 100644
index 0000000..8c767b2
--- /dev/null
+++ b/tests/openpgp/samplemsgs/sig-2-keys-1.asc
@@ -0,0 +1,15 @@
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v2
+
+iHsEABYIACMFAldqTMccHHBhdHJpY2UubHVtdW1iYUBleGFtcGxlLm5ldAAKCRAT
+lWNoKgINCgcQAP0f1yNJcHiBvy3nK7SSuzBf1EgSpy/lFlVSjZ1e/7CEKQD/W68C
+Zs8iGAyZplpsXKoz/g7LWSU5z/K3lLWwfre7gAGJATQEAAEIAB4FAldqTMcXHHN0
+ZXZlLmJpa29AZXhhbXBsZS5uZXQACgkQqkPx3Mf+0bdg8wf/ff4tEMfqdwk1dXJm
+4+iyrNvKyCfv/T5W8BVL16wc8jn+80HJkHK/pSw5Rr6nsEf1P00u5AnothUPfUl2
+Yqvjg4+oQYvutePo1uLq0LA1lyWfQ1PV6I14B/dd9rBYdPjYIJJsPjr/k5N3Qz9M
+8RNtDp/rPDVNVHzDbZN77oGE2jokGRfodRo6qnurqU4CnJYinrnzKV4wqrilNKlE
+R2CBieb3riDFUH59PH9S9fHuTHBV7q0HlxNJkI6NeoFwtRcS2f8P5B7FK7VCMrUB
+R46JExeWhvUlY2ZkKLU98bI3TLnFD0aQHRzKgJj8sWjD+Akzf408EmnOIyyf6MF8
+H7uIHg==
+=ErBQ
+-----END PGP SIGNATURE-----
diff --git a/tests/openpgp/samplemsgs/sig-2-keys-2.asc b/tests/openpgp/samplemsgs/sig-2-keys-2.asc
new file mode 100644
index 0000000..16ae64c
--- /dev/null
+++ b/tests/openpgp/samplemsgs/sig-2-keys-2.asc
@@ -0,0 +1,15 @@
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v2
+
+iQE0BAABCAAeBQJXakzUFxxzdGV2ZS5iaWtvQGV4YW1wbGUubmV0AAoJEKpD8dzH
+/tG3B8EH/247hq+cJ8eR8eXb1mv1Bdj9SwYI4yDs/xCZ7FIkU8vVSRYQpeYz59ie
+3WZw8Cj1Sd44tr3+viVK682lWXwpHIAl3xUizP+HTFs23tfyH3er7IhDO/aApZ+V
+Wd+0oDJY7E/ztsD3CpU50ptKU9D72CgJT8K1/pwBtivzOiMto/scPwVFNDzGlny8
+FC06j+2FyXFkXCLwvz/Xdk+hJmv8lQRGNxnSIB5bU+0/GLEd9wJUFTV3WSs5enEM
+zqtGBh6v395BXnqrDHpOmT+EkWrpBOSo5vkPZrbN4bOC9nKSa9isCvU/+fjHW3Dn
+GpHVTH1hCWsKRhQjxuOOq/X21YpvgJ2IewQAFggAIwUCV2pM1BwccGF0cmljZS5s
+dW11bWJhQGV4YW1wbGUubmV0AAoJEBOVY2gqAg0KPJMA/0+3s4HPotwYw8K8pug3
+7Mxgd9LNIBi/d0nSpBnZTHySAQDURAoIZp0IZI/PS7Jc9A8M3TgWdm1LUkj+qU9x
+3L6RCQ==
+=3oWb
+-----END PGP SIGNATURE-----
diff --git a/tests/openpgp/samplemsgs/signed-1-key-1.asc b/tests/openpgp/samplemsgs/signed-1-key-1.asc
new file mode 100644
index 0000000..d71c74d
--- /dev/null
+++ b/tests/openpgp/samplemsgs/signed-1-key-1.asc
@@ -0,0 +1,15 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+owGbwMvMwMG4yvnjneP/Lm5nPJ2exBCe5XbZI7E8O7UyVb1YwTk/LzmntDgzP8+K
+i9OzBCiSl1+ikJpYXKlQkq9QkJMIpDNSFZJz8svzFMozUvMUKvNL1ctSFdKByoAq
+ikrzwArKM/JzUrk4kzOLkkuL9bg6GU1YGBg5GORYmUD2icsUl6SWpeolZWbnO6RW
+JOYW5KTq5aWWMHBxCsAcl9zJ/od/6lrXa9snvZR9wrpXuEblNq/F3pzYWed8DZd8
+aApUzgkTy1K64+QU7HuL525G4vM3Yibfvq+VLTf/aFx46FSc7I2MpE2vElhvztZ5
+8SQ2ZWe7m5apT9qu7UfXyhrxxfutyt+ot3daXp3hyxuVPzdfKD147N8djoc5634y
+6n9Uvfa7Uec030zZjae3VHScMDY1tD7yQjrFNnXptYQXP+RPtD1l+Kn33I87jeHT
+SYnUk8r3zD71zahJbfZYwem0c+WbOzs/+qQeKeE/kaL+Y8GHeY9vbkq6eGNKWag+
+Y+Ydhac6bccZHEpXHFBfy3iBJ9OrZub93Oulx4Tnz5U5tZuL31VZOSzlyESvoJeb
+/0kDAA==
+=T94L
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/samplemsgs/signed-1-key-2.asc b/tests/openpgp/samplemsgs/signed-1-key-2.asc
new file mode 100644
index 0000000..64483fb
--- /dev/null
+++ b/tests/openpgp/samplemsgs/signed-1-key-2.asc
@@ -0,0 +1,12 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+owGbwMvMwCEmPDU5Q4uJl4vx9AG9JIbwLLcnnCHl+Qq5qXkKOfn52akpCvmlJQpp
+Rfm5CiUZqQoFRZnF+XkKSYlFxTpcnP55qQrFieUKuaUpurpcnCFABflAVUVgweIS
+oCI9Li6//HKFnNQSoJEK6UCqJCOzWKEoMz2jxEqhBGgTxMTUomKFxKJUsJ2Zeelg
+S0H2lWfmpeSX63GFZ2TmAA0H2pefBpLIVShPLIarTixRSMzJAWsAOkVBVxfMhDgF
+pCc9v0QhI7OEKzMPLJGRmpiix9VRzcIgxsGgzMoE8rWMTEFiSVFmcqpeTmluaW5S
+okNqRWJuQU6qXl5qCQMXpwAsoD78YWRY1rZ/7kOLr4GrbvSU6HqKnVy6+1BllLYd
+c5ebbu2ltZ89GRkOBN6327Z+J4eaa5ppOGeA08P8xgvlcft8tz5u9i7jncwKAA==
+=uuW/
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/samplemsgs/signed-2-keys-1.asc b/tests/openpgp/samplemsgs/signed-2-keys-1.asc
new file mode 100644
index 0000000..38d25b1
--- /dev/null
+++ b/tests/openpgp/samplemsgs/signed-2-keys-1.asc
@@ -0,0 +1,17 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+owGbwMvMwMG4yvnjneP/Lm5nmADiiglPTc7QYuLlYjwdm8QQnuVu45iTo+CWmZeY
+npOq4JNYXqyQm1ipkJSqkFRZkFhcnJoCZCjkpCYW5WXmpSuUZKQqFGfmFgDVJhaV
+KOSnKaTkA8W5yjNLMvJLS4DymXnZQAE9ro5qFgYxDgZlViaQJTIyBYklRZnJqXo5
+pbmluUmJDqkViSBj9PJSSxi4OAVgzpoVw/A/fBVnTGzGFd0DUzZcu6HNcm/6mpaZ
+CeuOc+89eOsmg9YGRYb/5U3LTx4pf5Ru3ceW/X+Vkdq22kuGCxqaVwYJHZSL/xfN
+08lowsLAyMEgB7FdXKa4JLUsVS8pMzsf3WJY8LR2sv/P9VLy+VZyrvhebd6WMyoz
+V/kIXW+p2WbcI1vw58xdofBbU9eHtM2Y47ft6Bm5bS0NL6d6zzl7YsfLl5qKLFJb
+s/cVKFe1MM7POqrEqzEr7cqe3amsN08ntDsvbLr3tc1ATKhTgMVKMIhjznseR54F
+L1tyl7eUv96SYCbIf+uzu5vZnjWHvulP1zm579qel7afa77Enc94Nnn+U4Xf7F8W
+PA5Kumj01S639ux3PcYFLR9+tey0bTDyNPhkqiddvLY9O8ztd94SDw4ph4+bbol+
+5S1+5dJ1vl1w7VSbtSf5dPfV1uxLr7UQnvGiwplnVpzt8XOvFXbHZ6yx2Hm52Kry
+0TndFZfZqkRzFGxn7bkOAA==
+=iswv
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/samplemsgs/signed-2-keys-2.asc b/tests/openpgp/samplemsgs/signed-2-keys-2.asc
new file mode 100644
index 0000000..5219e13
--- /dev/null
+++ b/tests/openpgp/samplemsgs/signed-2-keys-2.asc
@@ -0,0 +1,24 @@
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v2
+
+owFdk21sFFUUhqcf4O7wIQQLpi71skoKZFj4wUdrgiwYxVaUFrZUvkzuzJ7ZuezM
+3M3Mnd2OEpNiTVGTQlSKUn+A1WjBBFMDRIWAKG0qJYEWhVKgkECqBkrQ8AM1u96Z
+hVT9NTmZc573ve+5d8eEIiEwdcpORZtTOEEUdnhlwb5n7lzqzp49XHDqV1mo37xi
+ZTC8jjrIAGxKiKjI5QXWdZpBTANkYJuBhRhFMiDHVEia6JJXMgsw85pFbLqI6nGU
+wS7iEzpJgi0hbMa9NmLaju73WShOEiZhruSBTeTDXRQHMHyMSpg3oAG2kEZslCaQ
+QVTlzcRM2EvDYjBc6xAGvi2FmszClhtByDfv2IyTVOCivhQxGSQsXwzbtmNwhOgd
+TMNpGP3p6eWnOGe549v8D4tbMqmsc4pJGZJdkRiEYcZpvkWaMZEXlAycS6jFKVX3
+A7QAJcBkOqCMBrzgnvmARZ2EJolktClFde9M/27iKVOHaaMxZYiuIwsUyuN7FfKj
+tpiijAsQvioXZajFNDcvzwfiFGzP8SiC+DXC9/fJU1H5J+YtWhJxPjV/HSqAjlQL
+wMsmSZSkf1CeYYQvIDh3LopRA62msswXK6FwNWGcIzsJVAOW6hgQFt8qWFAsFASE
+sjGF3u2aFuKCaYjIJEmj0ICNlA4RE5ggBic9uIpd6kPZyjdLVjSdbP+96b2J2rhc
+6bKGZXtvnJv+1L7wY4MZdSC06tOxx74KzS7rosOTWn6MbN8wPHT1txnNVwJjRnpz
+j7wxs7uxV5+8dsPWRzsbetK3bx0emD0wuWfhJ92pNT8fbNh1oO5O1clXbo9r6u96
+ePDQ3ujiwc9PPP3n+x+t7r320xKnONu3deXGlmhh4+nhDyraXv871ifYtUvGt7Wd
+jw0PdexeVDLyS1Wd3tizqXx/y/XpFaj1h7e3dLofJ7+YX8NK9xRFrweaZ/4hvTy2
+dekL+w+tiu3JFlX2GJ+VH6m7cXHdc3drl3//+MXO6tx3E53si32nDo7ULO5o73qp
+XbnUG2xtP13XX7roKB3Z9lqxMDUgPJFPLRRKYWYRBSK6YziGjP8f3YNHXV4v5BTt
+5qbStev/6ghX7xz/4e4jQ09Wtm5898Ss4LfbmkswuyDkttyc9807ZRfmfX3m+Vv1
+/bO+HIzB9sv3pGjwzHGlv+JZ8R8=
+=pstx
+-----END PGP MESSAGE-----
diff --git a/tests/openpgp/seat.scm b/tests/openpgp/seat.scm
new file mode 100755
index 0000000..5cbfbe1
--- /dev/null
+++ b/tests/openpgp/seat.scm
@@ -0,0 +1,31 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(for-each-p
+ "Checking encryption, signing, and producing armored output"
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg usrpass1 '(--yes -seat -r two@example.com --passphrase-fd "0"))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-weak-identity source)))
+ plain-files)
diff --git a/tests/openpgp/secdemo.asc b/tests/openpgp/secdemo.asc
new file mode 100644
index 0000000..343453c
--- /dev/null
+++ b/tests/openpgp/secdemo.asc
@@ -0,0 +1,737 @@
+26 demo keys (passphrase is "abc"):
+
+sec 1024D/68697734 1999-03-08 Alpha Test (demo key) <alpha@example.net>
+uid Alice (demo key)
+uid Alfa Test (demo key) <alfa@example.net>
+ssb 1024g/46A871F8 1999-03-08
+sec 1024D/1AFDAB6C 1999-03-08 Charlie Test (demo key) <charlie@example.net>
+ssb 1024g/BC43DA60 1999-03-08
+sec 1024D/FAEF6D1B 1999-03-08 Echo Test (demo key) <echo@example.net>
+uid Eve (demo key)
+uid Echelon (demo key)
+ssb 1024g/7272144D 1999-03-08
+sec 1024D/8FC282E6 1999-03-08 Golf Test (demo key) <golf@example.net>
+ssb 1024g/9DCAD354 1999-03-08
+sec 1024D/04259677 1999-03-08 India Test (demo key) <india@example.net>
+ssb 1024g/61F76C73 1999-03-08
+sec 1024D/43C2D0C7 1999-03-08 Kilo Test (demo key) <kilo@example.net>
+ssb 1024g/9AF64D02 1999-03-08
+sec 1024D/A9E3B0B2 1999-03-08 Bravo Test (demo key) <bravo@example.net>
+uid Bob (demo key)
+ssb 1024g/E29BA37F 1999-03-08
+sec 1024D/EB9DC9E6 1999-03-08 Delta Test (demo key) <delta@example.net>
+ssb 1024g/B0C45424 1999-03-08
+sec 1024D/7372E243 1999-03-08 Foxtrot Test (demo key) <foxtrot@example.net>
+ssb 1024g/EE45198E 1999-03-08
+sec 1024D/34C6E3F1 1999-03-08 Hotel Test (demo key) <hotel@example.net>
+ssb 1024g/D622AD0A 1999-03-08
+sec 1024D/D2699313 1999-03-08 Juliet Test (demo key) <juliet@example.net>
+ssb 1024g/35F8F136 1999-03-08
+sec 1024D/B79103F8 1999-03-08 Lima Test (demo key) <lima@example.net>
+ssb 1024g/FE56350C 1999-03-08
+sec 1024D/BE5CF886 1999-03-08 Mike Test (demo key) <mike@example.net>
+uid Mallory (demo key)
+ssb 1024g/4F31EAE8 1999-03-08
+sec 1024D/30CEC684 1999-03-08 November Test (demo key) <november@example.net>
+ssb 1024g/8B70E472 1999-03-08
+sec 1024D/6D9732AC 1999-03-08 Oscar Test (demo key) <oscar@example.net>
+ssb 1024g/2681619F 1999-03-08
+sec 1024D/3FF13206 1999-03-08 Papa test (demo key) <papa@example.net>
+ssb 1024g/63330D9C 1999-03-08
+sec 1024D/3C661C84 1999-03-08 Quebec Test (demo key) <quebec@example.net>
+ssb 1024g/A029ACF4 1999-03-08
+sec 1024D/777FBED3 1999-03-08 Romeo Test (demo key) <romeo@example.net>
+ssb 1024g/11D102EA 1999-03-08
+sec 1024D/A3AE3EA1 1999-03-08 Sierra Test (demo key) <sierra@example.net>
+ssb 1024g/0F1B50B4 1999-03-08
+sec 1024D/85A81F38 1999-03-08 Tango Test (demo key) <tango@example.net>
+ssb 1024g/101C0402 1999-03-08
+sec 1024D/653244D6 1999-03-08 Uniform Test (demo key) <uniform@example.net>
+ssb 1024g/5522BDB9 1999-03-08
+sec 1024D/61F04784 1999-03-08 Victor Test (demo key) <victor@example.org>
+ssb 1024g/07287134 1999-03-08
+sec 1024D/EC67DBDE 1999-03-08 Whisky Test (demo key) <whisky@example.net>
+ssb 1024g/FD6E27F6 1999-03-08
+sec 1024D/567FB34A 1999-03-08 XRay Test (demo key) <xray@example.net>
+ssb 1024g/41E408BE 1999-03-08
+sec 1024D/4B11B25F 1999-03-08 Yankee Test (demo key) <yankee@example.net>
+ssb 1024g/F7B080AD 1999-03-08
+sec 1024D/54ACD246 1999-03-08 Zulu Test (demo key) <zulu@example.net>
+ssb 1024g/A172C881 1999-03-08
+
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v0.9.3 (GNU/Linux)
+Comment: For info see http://www.gnupg.org
+
+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
+=P9+G
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp/secring.asc b/tests/openpgp/secring.asc
new file mode 100644
index 0000000..99e02ca
--- /dev/null
+++ b/tests/openpgp/secring.asc
@@ -0,0 +1,73 @@
+This is a test secret keyring simply stored by GNUPG so that it is
+easier to make diff files.
+
+sec 1024D/D74C5F22 2003-12-31 Test one (pp=def) <one@example.com>
+ssb 1024g/47BE2775 2003-12-31
+
+sec 1024D/C40FDECF 2003-12-31 Test two (no pp) <two@example.com>
+ssb 1024g/B27907AA 2003-12-31
+
+sec 1024R/ECABF51D 2003-12-31 Test three (no pp) <three@example.com>
+
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1.3.5-cvs (GNU/Linux)
+
+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
+IHWHiQ==
+=52aT
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp/secring.skr.asc b/tests/openpgp/secring.skr.asc
new file mode 100644
index 0000000..0081b59
--- /dev/null
+++ b/tests/openpgp/secring.skr.asc
@@ -0,0 +1,27 @@
+This is a test secring generated by pgp 5 beta
+
+Type Bits KeyID Created Expires Algorithm Use
+sec+ 768 439F02CA 1998-03-17 ---------- DSS Sign and Encrypt
+sub 768 CB879DE9 1998-03-17 ---------- Diffie-Hellman
+uid pgp5 test <pgp5@dev.null>
+
+There is no password on the key
+
+-----BEGIN PGP ARMORED FILE-----
+Version: GNUPG v0.2.13a (Linux)
+Comment: This is an alpha version!
+Comment: Use "gpgm --dearmor" for unpacking
+
+lQFbBDUOrE4RAwDbbxWAbWsheUJprK6VryMTpwDiYwMfL+92nrHqSfPqlpMWgDTia8qnpRSXbyEm
+Sppp/6/Ygp+N3n32Kznq7PjHXiuWLlZGvZMtzmvaMA17y0GY6oLBxS7rhASXIKa9hEUAoP+KBFly
+qNMdsK8j+ZO0A8rnImGrAwC1ddDme5iZFkTEWHhrtU97sEu2GDkSQB8HdX8CoRcrOz/B2WliF6qf
+BKhcZPFVBIhKNzjTfY7SEYAZk2zcsCm8elnwSLaGEzxKFNFBqKDNXP+a35spcqsHSGzDVw4VuKMD
+AJNnAP6skpHlhVAmecLZT9eRzVoOq1ivUIntK2Mh47qsL74q6BBwz2sviPU2Y3pDlbb6Ed0qJAXv
+dCT24hlfoGoXzkoDInkPJTJeL0gCnwmQPjvXFFd71Cvg5LaL4lIQLQAAn3GbgsWo+7E/hWakzstp
+TXzI2kDIDIm0GXBncDUgdGVzdCA8cGdwNUBkZXYubnVsbD6dAO8ENQ6sVhADAP8Fa5TbD6k8VmW1
+IjK1DfDI0xUdsVIbk8N3Hb0YIlT1E/6tZdfiNwqaKVQcf17gJIObBwfNM3OqWYOudmBVd3S6E3Hk
+u64nW+ZNt7B2toWRgnk6OgHcSDsud4Igjwz/RQACAgL/ToefzlcVKiPuobKfXHDhIUQPTfGic2Az
+47wkMoYHo9j9ZE7AWaliMdPz4jLyLfqqoU9mH8g+vJhyAc7UnAF2Sk5466FDypdPm5F9PTW3cqqI
+wJM4WgkSlM8J2hxH4YtlAADlG+pxFXNFuDPmcq6jL6dug2ikZ7hcHLAy7DddSS8OAA==
+=1UWo
+-----END PGP ARMORED FILE-----
diff --git a/tests/openpgp/setup.scm b/tests/openpgp/setup.scm
new file mode 100755
index 0000000..22c89a3
--- /dev/null
+++ b/tests/openpgp/setup.scm
@@ -0,0 +1,49 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+
+(define cache (flag "--create-tarball" *args*))
+(unless (and cache (= 1 (length cache)))
+ (fail "Usage: setup.scm --create-tarball <file> [--use-keyring]"))
+
+(when (> (*verbose*) 0)
+ (define (pad symbol length)
+ (let loop ((cs (string->list (symbol->string symbol)))
+ (result (make-string length #\space))
+ (i 0))
+ (if (null? cs)
+ result
+ (begin
+ (string-set! result i (car cs))
+ (loop (cdr cs) result (+ 1 i))))))
+ (log " I am going to use these tools:\n"
+ "==============================")
+ (for-each
+ (lambda (t)
+ (log (pad t 25) (tool t)))
+ '(gpgconf gpg gpg-agent scdaemon gpgsm dirmngr gpg-connect-agent
+ gpg-preset-passphrase gpgtar pinentry)))
+
+(setenv "GNUPGHOME" (getcwd) #t)
+(create-gpghome)
+(start-agent)
+(create-legacy-gpghome)
+(stop-agent)
+(call-check `(,(tool 'gpgtar) --create --output ,(car cache) "."))
diff --git a/tests/openpgp/shell.scm b/tests/openpgp/shell.scm
new file mode 100644
index 0000000..347b3a0
--- /dev/null
+++ b/tests/openpgp/shell.scm
@@ -0,0 +1,53 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+
+;; This is not a test, but can be used to inspect the test
+;; environment. Simply execute
+;;
+;; make -Ctests/openpgp check XTESTS=shell.scm
+;;
+;; to run it.
+
+(if (prompt-yes-no? "Load legacy test environment" #t)
+ (setup-legacy-environment)
+ (setup-environment))
+
+(if (prompt-yes-no? "Drop 'batch' from gpg.conf" #t)
+ (apply create-file
+ (cons "gpg.conf"
+ (filter (lambda (line) (not (equal? "batch" line)))
+ (string-split-newlines
+ (call-with-input-file "gpg.conf" read-all)))))
+ (begin
+ (echo "Note that gpg.conf includes 'batch'. If you want to use gpg")
+ (echo "interactively you should drop that.")))
+
+;; Add paths to tools to PATH.
+(setenv "PATH" (pathsep-join
+ (append (map (lambda (t) (dirname (tool t)))
+ '(gpg gpg-agent scdaemon gpgsm dirmngr gpgconf))
+ (pathsep-split (getenv "PATH"))))
+ #t)
+
+(echo "\nEnjoy your test environment. "
+ "Type 'exit' to exit it, it will be cleaned up after you.\n")
+
+(interactive-shell)
diff --git a/tests/openpgp/signdemokey b/tests/openpgp/signdemokey
new file mode 100755
index 0000000..13c5784
--- /dev/null
+++ b/tests/openpgp/signdemokey
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+set -e
+
+if [ $# != 3 ]; then
+ echo "Usage: signdemokey name user_id user_id_no"
+ exit 1
+fi
+name="$1"
+user_id="$2"
+user_id_no="$3"
+
+echo "abc" | ../g10/gpg --options ./gpg.conf --homedir $name \
+ --sign-key --batch --yes --passphrase-fd 0 $user_id \
+ $user_id_no sign save
+
diff --git a/tests/openpgp/signed-messages.scm b/tests/openpgp/signed-messages.scm
new file mode 100644
index 0000000..d012f2f
--- /dev/null
+++ b/tests/openpgp/signed-messages.scm
@@ -0,0 +1,281 @@
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+;; A plain signed message created using
+;; echo abc | gpg --homedir . --passphrase-fd 0 -u Alpha -z0 -sa msg
+(define msg_ols_asc "
+-----BEGIN PGP MESSAGE-----
+
+kA0DAAIRLXJ8x2hpdzQBrQEHYgNtc2dEDFJaSSB0aGluayB0aGF0IGFsbCByaWdo
+dC10aGlua2luZyBwZW9wbGUgaW4gdGhpcyBjb3VudHJ5IGFyZSBzaWNrIGFuZAp0
+aXJlZCBvZiBiZWluZyB0b2xkIHRoYXQgb3JkaW5hcnkgZGVjZW50IHBlb3BsZSBh
+cmUgZmVkIHVwIGluIHRoaXMKY291bnRyeSB3aXRoIGJlaW5nIHNpY2sgYW5kIHRp
+cmVkLiAgSSdtIGNlcnRhaW5seSBub3QuICBCdXQgSSdtCnNpY2sgYW5kIHRpcmVk
+IG9mIGJlaW5nIHRvbGQgdGhhdCBJIGFtLgotIE1vbnR5IFB5dGhvbgqIPwMFAEQM
+UlotcnzHaGl3NBECR4IAoJlEGTY+bHjD2HYuCixLQCmk01pbAKCIjkzLOAmkZNm0
+D8luT78c/1x45Q==
+=a29i
+-----END PGP MESSAGE-----
+")
+
+;; A plain signed message created using
+;; echo abc | gpg --homedir . --passphrase-fd 0 -u Alpha -sa msg
+(define msg_cols_asc "
+-----BEGIN PGP MESSAGE-----
+
+owGbwMvMwCSoW1RzPCOz3IRxLSN7EnNucboLT6Cgp0JJRmZeNpBMLFFIzMlRKMpM
+zyjRBQtm5qUrFKTmF+SkKmTmgdQVKyTnl+aVFFUqJBalKhRnJmcrJOalcJVkFqWm
+KOSnKSSlgrSU5OekQMzLL0rJzEsEKk9JTU7NK4EZBtKcBtRRWgAzlwtmbnlmSQbU
+GJjxCmDj9RQUPNVzFZJTi0oSM/NyKhXy8kuAYk6lJSBxLlTF2NziqZCYq8elq+Cb
+n1dSqRBQWZKRn8fVYc/MygAKBljYCDIFiTDMT+9seu836Q+bevyHTJ0dzPNuvCjn
+ZpgrwX38z58rJsfYDhwOSS4SkN/d6vUAAA==
+=s6sY
+-----END PGP MESSAGE-----
+")
+
+;; A PGP 2 style message.
+(define msg_sl_asc "
+-----BEGIN PGP MESSAGE-----
+
+iD8DBQBEDFJaLXJ8x2hpdzQRAkeCAKCZRBk2Pmx4w9h2LgosS0AppNNaWwCgiI5M
+yzgJpGTZtA/Jbk+/HP9ceOWtAQdiA21zZ0QMUlpJIHRoaW5rIHRoYXQgYWxsIHJp
+Z2h0LXRoaW5raW5nIHBlb3BsZSBpbiB0aGlzIGNvdW50cnkgYXJlIHNpY2sgYW5k
+CnRpcmVkIG9mIGJlaW5nIHRvbGQgdGhhdCBvcmRpbmFyeSBkZWNlbnQgcGVvcGxl
+IGFyZSBmZWQgdXAgaW4gdGhpcwpjb3VudHJ5IHdpdGggYmVpbmcgc2ljayBhbmQg
+dGlyZWQuICBJJ20gY2VydGFpbmx5IG5vdC4gIEJ1dCBJJ20Kc2ljayBhbmQgdGly
+ZWQgb2YgYmVpbmcgdG9sZCB0aGF0IEkgYW0uCi0gTW9udHkgUHl0aG9uCg==
+=0ukK
+-----END PGP MESSAGE-----
+")
+
+;; An OpenPGP message lacking the onepass packet. We used to accept
+;; such messages but now consider them invalid.
+(define bad_ls_asc "
+-----BEGIN PGP MESSAGE-----
+
+rQEHYgNtc2dEDFJaSSB0aGluayB0aGF0IGFsbCByaWdodC10aGlua2luZyBwZW9w
+bGUgaW4gdGhpcyBjb3VudHJ5IGFyZSBzaWNrIGFuZAp0aXJlZCBvZiBiZWluZyB0
+b2xkIHRoYXQgb3JkaW5hcnkgZGVjZW50IHBlb3BsZSBhcmUgZmVkIHVwIGluIHRo
+aXMKY291bnRyeSB3aXRoIGJlaW5nIHNpY2sgYW5kIHRpcmVkLiAgSSdtIGNlcnRh
+aW5seSBub3QuICBCdXQgSSdtCnNpY2sgYW5kIHRpcmVkIG9mIGJlaW5nIHRvbGQg
+dGhhdCBJIGFtLgotIE1vbnR5IFB5dGhvbgqIPwMFAEQMUlotcnzHaGl3NBECR4IA
+oJlEGTY+bHjD2HYuCixLQCmk01pbAKCIjkzLOAmkZNm0D8luT78c/1x45Q==
+=Mpiu
+-----END PGP MESSAGE-----
+")
+
+
+;; A signed message prefixed with an unsigned literal packet.
+;; (fols = faked-literal-data, one-pass, literal-data, signature)
+;; This should throw an error because running gpg to extract the
+;; signed data will return both literal data packets
+(define bad_fols_asc "
+-----BEGIN PGP MESSAGE-----
+
+rF1iDG1zZy51bnNpZ25lZEQMY0x0aW1lc2hhcmluZywgbjoKCUFuIGFjY2VzcyBt
+ZXRob2Qgd2hlcmVieSBvbmUgY29tcHV0ZXIgYWJ1c2VzIG1hbnkgcGVvcGxlLgqQ
+DQMAAhEtcnzHaGl3NAGtAQdiA21zZ0QMUlpJIHRoaW5rIHRoYXQgYWxsIHJpZ2h0
+LXRoaW5raW5nIHBlb3BsZSBpbiB0aGlzIGNvdW50cnkgYXJlIHNpY2sgYW5kCnRp
+cmVkIG9mIGJlaW5nIHRvbGQgdGhhdCBvcmRpbmFyeSBkZWNlbnQgcGVvcGxlIGFy
+ZSBmZWQgdXAgaW4gdGhpcwpjb3VudHJ5IHdpdGggYmVpbmcgc2ljayBhbmQgdGly
+ZWQuICBJJ20gY2VydGFpbmx5IG5vdC4gIEJ1dCBJJ20Kc2ljayBhbmQgdGlyZWQg
+b2YgYmVpbmcgdG9sZCB0aGF0IEkgYW0uCi0gTW9udHkgUHl0aG9uCog/AwUARAxS
+Wi1yfMdoaXc0EQJHggCgmUQZNj5seMPYdi4KLEtAKaTTWlsAoIiOTMs4CaRk2bQP
+yW5Pvxz/XHjl
+=UNM4
+-----END PGP MESSAGE-----
+")
+
+;; A signed message suffixed with an unsigned literal packet.
+;; (fols = faked-literal-data, one-pass, literal-data, signature)
+;; This should throw an error because running gpg to extract the
+;; signed data will return both literal data packets
+(define bad_olsf_asc "
+-----BEGIN PGP MESSAGE-----
+
+kA0DAAIRLXJ8x2hpdzQBrQEHYgNtc2dEDFJaSSB0aGluayB0aGF0IGFsbCByaWdo
+dC10aGlua2luZyBwZW9wbGUgaW4gdGhpcyBjb3VudHJ5IGFyZSBzaWNrIGFuZAp0
+aXJlZCBvZiBiZWluZyB0b2xkIHRoYXQgb3JkaW5hcnkgZGVjZW50IHBlb3BsZSBh
+cmUgZmVkIHVwIGluIHRoaXMKY291bnRyeSB3aXRoIGJlaW5nIHNpY2sgYW5kIHRp
+cmVkLiAgSSdtIGNlcnRhaW5seSBub3QuICBCdXQgSSdtCnNpY2sgYW5kIHRpcmVk
+IG9mIGJlaW5nIHRvbGQgdGhhdCBJIGFtLgotIE1vbnR5IFB5dGhvbgqIPwMFAEQM
+UlotcnzHaGl3NBECR4IAoJlEGTY+bHjD2HYuCixLQCmk01pbAKCIjkzLOAmkZNm0
+D8luT78c/1x45axdYgxtc2cudW5zaWduZWREDGNMdGltZXNoYXJpbmcsIG46CglB
+biBhY2Nlc3MgbWV0aG9kIHdoZXJlYnkgb25lIGNvbXB1dGVyIGFidXNlcyBtYW55
+IHBlb3BsZS4K
+=3gnG
+-----END PGP MESSAGE-----
+")
+
+
+;; Two standard signed messages in a row
+(define msg_olsols_asc_multiple "
+-----BEGIN PGP MESSAGE-----
+
+kA0DAAIRLXJ8x2hpdzQBrQEHYgNtc2dEDFJaSSB0aGluayB0aGF0IGFsbCByaWdo
+dC10aGlua2luZyBwZW9wbGUgaW4gdGhpcyBjb3VudHJ5IGFyZSBzaWNrIGFuZAp0
+aXJlZCBvZiBiZWluZyB0b2xkIHRoYXQgb3JkaW5hcnkgZGVjZW50IHBlb3BsZSBh
+cmUgZmVkIHVwIGluIHRoaXMKY291bnRyeSB3aXRoIGJlaW5nIHNpY2sgYW5kIHRp
+cmVkLiAgSSdtIGNlcnRhaW5seSBub3QuICBCdXQgSSdtCnNpY2sgYW5kIHRpcmVk
+IG9mIGJlaW5nIHRvbGQgdGhhdCBJIGFtLgotIE1vbnR5IFB5dGhvbgqIPwMFAEQM
+UlotcnzHaGl3NBECR4IAoJlEGTY+bHjD2HYuCixLQCmk01pbAKCIjkzLOAmkZNm0
+D8luT78c/1x45ZANAwACES1yfMdoaXc0Aa0BB2IDbXNnRAxSWkkgdGhpbmsgdGhh
+dCBhbGwgcmlnaHQtdGhpbmtpbmcgcGVvcGxlIGluIHRoaXMgY291bnRyeSBhcmUg
+c2ljayBhbmQKdGlyZWQgb2YgYmVpbmcgdG9sZCB0aGF0IG9yZGluYXJ5IGRlY2Vu
+dCBwZW9wbGUgYXJlIGZlZCB1cCBpbiB0aGlzCmNvdW50cnkgd2l0aCBiZWluZyBz
+aWNrIGFuZCB0aXJlZC4gIEknbSBjZXJ0YWlubHkgbm90LiAgQnV0IEknbQpzaWNr
+IGFuZCB0aXJlZCBvZiBiZWluZyB0b2xkIHRoYXQgSSBhbS4KLSBNb250eSBQeXRo
+b24KiD8DBQBEDFJaLXJ8x2hpdzQRAkeCAKCZRBk2Pmx4w9h2LgosS0AppNNaWwCg
+iI5MyzgJpGTZtA/Jbk+/HP9ceOU=
+=8nLN
+-----END PGP MESSAGE-----
+")
+
+;; A standard message with two signatures (actually the same signature
+;; duplicated).
+(define msg_oolss_asc "
+-----BEGIN PGP MESSAGE-----
+
+kA0DAAIRLXJ8x2hpdzQBkA0DAAIRLXJ8x2hpdzQBrQEHYgNtc2dEDFJaSSB0aGlu
+ayB0aGF0IGFsbCByaWdodC10aGlua2luZyBwZW9wbGUgaW4gdGhpcyBjb3VudHJ5
+IGFyZSBzaWNrIGFuZAp0aXJlZCBvZiBiZWluZyB0b2xkIHRoYXQgb3JkaW5hcnkg
+ZGVjZW50IHBlb3BsZSBhcmUgZmVkIHVwIGluIHRoaXMKY291bnRyeSB3aXRoIGJl
+aW5nIHNpY2sgYW5kIHRpcmVkLiAgSSdtIGNlcnRhaW5seSBub3QuICBCdXQgSSdt
+CnNpY2sgYW5kIHRpcmVkIG9mIGJlaW5nIHRvbGQgdGhhdCBJIGFtLgotIE1vbnR5
+IFB5dGhvbgqIPwMFAEQMUlotcnzHaGl3NBECR4IAoJlEGTY+bHjD2HYuCixLQCmk
+01pbAKCIjkzLOAmkZNm0D8luT78c/1x45Yg/AwUARAxSWi1yfMdoaXc0EQJHggCg
+mUQZNj5seMPYdi4KLEtAKaTTWlsAoIiOTMs4CaRk2bQPyW5Pvxz/XHjl
+=KVw5
+-----END PGP MESSAGE-----
+")
+
+;; A standard message with two one-pass packet but only one signature
+;; packet
+(define bad_ools_asc "
+-----BEGIN PGP MESSAGE-----
+
+kA0DAAIRLXJ8x2hpdzQBkA0DAAIRLXJ8x2hpdzQBrQEHYgNtc2dEDFJaSSB0aGlu
+ayB0aGF0IGFsbCByaWdodC10aGlua2luZyBwZW9wbGUgaW4gdGhpcyBjb3VudHJ5
+IGFyZSBzaWNrIGFuZAp0aXJlZCBvZiBiZWluZyB0b2xkIHRoYXQgb3JkaW5hcnkg
+ZGVjZW50IHBlb3BsZSBhcmUgZmVkIHVwIGluIHRoaXMKY291bnRyeSB3aXRoIGJl
+aW5nIHNpY2sgYW5kIHRpcmVkLiAgSSdtIGNlcnRhaW5seSBub3QuICBCdXQgSSdt
+CnNpY2sgYW5kIHRpcmVkIG9mIGJlaW5nIHRvbGQgdGhhdCBJIGFtLgotIE1vbnR5
+IFB5dGhvbgqIPwMFAEQMUlotcnzHaGl3NBECR4IAoJlEGTY+bHjD2HYuCixLQCmk
+01pbAKCIjkzLOAmkZNm0D8luT78c/1x45Q==
+=1/ix
+-----END PGP MESSAGE-----
+")
+
+;; Standard cleartext signature
+(define msg_cls_asc "
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+I think that all right-thinking people in this country are sick and
+tired of being told that ordinary decent people are fed up in this
+country with being sick and tired. I'm certainly not. But I'm
+sick and tired of being told that I am.
+- - Monty Python
+-----BEGIN PGP SIGNATURE-----
+
+iD8DBQFEDVp1LXJ8x2hpdzQRAplUAKCMfpG3GPw/TLN52tosgXP5lNECkwCfQhAa
+emmev7IuQjWYrGF9Lxj+zj8=
+=qJsY
+-----END PGP SIGNATURE-----
+")
+
+;; Cleartext signature with two signatures
+(define msg_clss_asc "
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+What is the difference between a Turing machine and the modern computer?
+It's the same as that between Hillary's ascent of Everest and the
+establishment of a Hilton on its peak.
+-----BEGIN PGP SIGNATURE-----
+
+iD8DBQFEDVz6LXJ8x2hpdzQRAtkGAKCeMhNbHnh339fpjNj9owsYcC4zBwCfYO5l
+2u+KEfXX0FKyk8SMzLjZ536IPwMFAUQNXPr+GAsdqeOwshEC2QYAoPOWAiQm0EF/
+FWIAQUplk7JWbyRKAJ92ZJyJpWfzb0yc1s7MY65r2qEHrg==
+=1Xvv
+-----END PGP SIGNATURE-----
+")
+
+;; Two clear text signatures in a row
+(define msg_clsclss_asc_multiple (string-append msg_cls_asc msg_clss_asc))
+
+
+;; An Ed25519 cleartext message with an R parameter of only 247 bits
+;; so that the code to re-insert the stripped zero byte kicks in. The
+;; S parameter has 253 bits but that does not strip a full byte.
+;;
+;; Note that the message has a typo ("the the"), but this should not
+;; be fixed because it breaks this test.
+(define msg_ed25519_rshort "
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA256
+
+Dear Emily:
+ I'm still confused as to what groups articles should be posted
+to. How about an example?
+ -- Still Confused
+
+Dear Still:
+ Ok. Let's say you want to report that Gretzky has been traded from
+the Oilers to the Kings. Now right away you might think rec.sport.hockey
+would be enough. WRONG. Many more people might be interested. This is a
+big trade! Since it's a NEWS article, it belongs in the news.* hierarchy
+as well. If you are a news admin, or there is one on your machine, try
+news.admin. If not, use news.misc.
+ The Oilers are probably interested in geology, so try sci.physics.
+He is a big star, so post to sci.astro, and sci.space because they are also
+interested in stars. Next, his name is Polish sounding. So post to
+soc.culture.polish. But that group doesn't exist, so cross-post to
+news.groups suggesting it should be created. With this many groups of
+interest, your article will be quite bizarre, so post to talk.bizarre as
+well. (And post to comp.std.mumps, since they hardly get any articles
+there, and a \"comp\" group will propagate your article further.)
+ You may also find it is more fun to post the article once in each
+group. If you list all the newsgroups in the same article, some newsreaders
+will only show the the article to the reader once! Don't tolerate this.
+ -- Emily Postnews Answers Your Questions on Netiquette
+-----BEGIN PGP SIGNATURE-----
+
+iJEEARYIADoWIQSyHeq0+HX7PaQvHR0TlWNoKgINCgUCV772DhwccGF0cmljZS5s
+dW11bWJhQGV4YW1wbGUubmV0AAoJEBOVY2gqAg0KMAIA90EtUwAja0iJGpO91wyz
+GLh9pS5v495V0r94yU6uUyUA/RT/StyPWe1wbnEZuacZnLbUV6Yy/aTXCVAlxf0r
+TusO
+=vQ3f
+-----END PGP SIGNATURE-----
+")
+
+;; An Ed25519 cleartext message with an S parameter of only 248 bits
+;; so that the code to re-insert the stripped zero byte kicks in.
+(define msg_ed25519_sshort "
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA256
+
+All articles that coruscate with resplendence are not truly auriferous.
+-----BEGIN PGP SIGNATURE-----
+
+iJEEARYIADoWIQSyHeq0+HX7PaQvHR0TlWNoKgINCgUCV771QhwccGF0cmljZS5s
+dW11bWJhQGV4YW1wbGUubmV0AAoJEBOVY2gqAg0KHVEBAI66OPDYXKWO3r6SaFT+
+uxmh8x4ZerW41vMA9gkJ4AEKAPjoe/Z7fDqo1lCptIFutFAGbfNxcm/53prfx2fT
+GisM
+=L7sk
+-----END PGP SIGNATURE-----
+")
diff --git a/tests/openpgp/signencrypt-dsa.scm b/tests/openpgp/signencrypt-dsa.scm
new file mode 100755
index 0000000..1a8f9df
--- /dev/null
+++ b/tests/openpgp/signencrypt-dsa.scm
@@ -0,0 +1,49 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(for-each-p
+ "Checking signing and encryption using DSA"
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg usrpass1 `(--yes --passphrase-fd "0" -se
+ -u ,dsa-usrname1
+ --recipient ,dsa-usrname2))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity source)))
+ (append plain-files data-files))
+
+(define algos (if (have-hash-algo? "RIPEMD160")
+ '("SHA1" "RIPEMD160")
+ '("SHA1")))
+(for-each-p
+ "Checking signing and encryption using DSA with a specific hash algorithm"
+ (lambda (hash)
+ (tr:do
+ (tr:open (car plain-files))
+ (tr:gpg usrpass1 `(--yes --passphrase-fd "0" -se
+ -u ,dsa-usrname1
+ --recipient ,dsa-usrname2
+ --digest-algo ,hash))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity (car plain-files))))
+ algos)
diff --git a/tests/openpgp/signencrypt.scm b/tests/openpgp/signencrypt.scm
new file mode 100755
index 0000000..c00e370
--- /dev/null
+++ b/tests/openpgp/signencrypt.scm
@@ -0,0 +1,41 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(for-each-p
+ "Checking signing and encryption"
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg usrpass1 `(--yes --passphrase-fd "0" -se --recipient ,usrname2))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity source)))
+ (append plain-files data-files))
+
+(info "Checking bug 537: MDC problem with old style compressed packets.")
+(lettmp (tmp)
+ (call-popen `(,@GPG --yes --passphrase-fd "0"
+ --output ,tmp --decrypt ,(in-srcdir "tests" "openpgp"
+ "bug537-test.data.asc"))
+ usrpass1)
+ (if (not (string=? "4336AE2A528FAE091E73E59E325B588FEE795F9B"
+ (cadar (gpg-hash-string `(--print-md SHA1 ,tmp) ""))))
+ (fail "bug537-test.data.asc: mismatch (bug 537)")))
diff --git a/tests/openpgp/sigs-dsa.scm b/tests/openpgp/sigs-dsa.scm
new file mode 100755
index 0000000..82dc624
--- /dev/null
+++ b/tests/openpgp/sigs-dsa.scm
@@ -0,0 +1,44 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(for-each-p
+ "Checking signing using DSA with the default hash algorithm"
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg "" `(--yes --sign --user ,dsa-usrname1))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity source)))
+ (append plain-files data-files))
+
+(define algos (if (have-hash-algo? "RIPEMD160")
+ '("SHA1" "RIPEMD160")
+ '("SHA1")))
+(for-each-p
+ "Checking signing using DSA with a specific hash algorithm"
+ (lambda (hash)
+ (tr:do
+ (tr:open (car plain-files))
+ (tr:gpg "" `(--yes --sign --user ,dsa-usrname1 --digest-algo ,hash))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity (car plain-files))))
+ algos)
diff --git a/tests/openpgp/sigs.scm b/tests/openpgp/sigs.scm
new file mode 100755
index 0000000..2b1cf3c
--- /dev/null
+++ b/tests/openpgp/sigs.scm
@@ -0,0 +1,51 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(for-each-p
+ "Checking signing with the default hash algorithm"
+ (lambda (source)
+ (tr:do
+ (tr:open source)
+ (tr:gpg "" '(--yes --sign))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity source)))
+ (append plain-files data-files))
+
+(for-each-p
+ "Checking signing with a specific hash algorithm"
+ (lambda (hash)
+ (if (have-pubkey-algo? "RSA")
+ ;; RSA key, so any hash is okay.
+ (tr:do
+ (tr:open (car plain-files))
+ (tr:gpg "" `(--yes --sign --user ,usrname3 --digest-algo ,hash))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity (car plain-files))))
+ (if (not (equal? "MD5" hash))
+ ;; Using the DSA sig key - only 160 bit or larger hashes
+ (tr:do
+ (tr:open (car plain-files))
+ (tr:gpg usrpass1
+ `(--yes --sign --passphrase-fd "0" --digest-algo ,hash))
+ (tr:gpg "" '(--yes --decrypt))
+ (tr:assert-identity (car plain-files)))))
+ (force all-hash-algos))
diff --git a/tests/openpgp/ssh-export.scm b/tests/openpgp/ssh-export.scm
new file mode 100755
index 0000000..136c6e0
--- /dev/null
+++ b/tests/openpgp/ssh-export.scm
@@ -0,0 +1,52 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-environment)
+
+(define key
+ `(,(in-srcdir "tests" "openpgp" "samplekeys" "authenticate-only.sec.asc")
+ "927EF377FD1A1B6F795E40C02A87917D8FFBA49F"
+ "72360FDB6380212D5DAF2FA9E51185A9253C496D"
+ "ssh-rsa"))
+
+(define :file car)
+(define :fpr cadr)
+(define :subkey-fpr caddr)
+(define :kind cadddr)
+
+;; Return true if a-str and b-str share a suffix of length n.
+(define (string-common-suffix? n a-str b-str)
+ (let ((a-len (string-length a-str))
+ (b-len (string-length b-str)))
+ (if (> n (min a-len b-len))
+ #f
+ (string=? (substring a-str (- a-len n) a-len)
+ (substring b-str (- b-len n) b-len)))))
+
+(info "Checking ssh export...")
+(call-check `(,@GPG --yes --import ,(:file key)))
+
+(let* ((result (call-check `(,@GPG --export-ssh-key ,(:fpr key))))
+ (parts (string-splitp (string-trim char-whitespace? result)
+ char-whitespace? -1)))
+ (assert (string=? (car parts) (:kind key)))
+ ;; XXX: We should not use a short keyid as the comment when
+ ;; exporting an ssh key.
+ (assert (string-common-suffix? 8 (caddr parts) (:subkey-fpr key))))
diff --git a/tests/openpgp/ssh-import.scm b/tests/openpgp/ssh-import.scm
new file mode 100755
index 0000000..555f198
--- /dev/null
+++ b/tests/openpgp/ssh-import.scm
@@ -0,0 +1,101 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-environment)
+
+(setenv "SSH_AUTH_SOCK"
+ (call-check `(,(tool 'gpgconf) --null --list-dirs agent-ssh-socket))
+ #t)
+
+(define path (string-split (getenv "PATH") *pathsep*))
+(define ssh #f)
+(catch (skip "ssh not found") (set! ssh (path-expand "ssh" path)))
+
+(define ssh-add #f)
+(catch (skip "ssh-add not found")
+ (set! ssh-add (path-expand "ssh-add" path)))
+
+(define ssh-keygen #f)
+(catch (skip "ssh-keygen not found")
+ (set! ssh-keygen (path-expand "ssh-keygen" path)))
+
+(define ssh-version-string
+ (:stderr (call-with-io `(,ssh "-V") "")))
+
+(log "Using" ssh "version:" ssh-version-string)
+
+(define ssh-version
+ (let ((tmp ssh-version-string)
+ (prefix "OpenSSH_"))
+ (unless (string-prefix? tmp prefix)
+ (skip "This doesn't look like OpenSSH:" tmp))
+ (string->number (substring tmp (string-length prefix)
+ (+ 3 (string-length prefix))))))
+
+(define (ssh-supports? algorithm)
+ ;; We exploit ssh-keygen as an oracle to test what algorithms ssh
+ ;; supports.
+ (cond
+ ((equal? algorithm "ed25519")
+ ;; Unfortunately, our oracle does not work for ed25519 because
+ ;; this is a specific curve and not a family, so the key size
+ ;; parameter is ignored.
+ (>= ssh-version 6.5))
+ (else
+ ;; We call ssh-keygen with the algorithm to test, specify an
+ ;; invalid key size, and observe the error message.
+ (let ((output (:stderr (call-with-io `(,ssh-keygen
+ -t ,algorithm
+ -b "1009") ""))))
+ (log "(ssh-supports?" algorithm "), ssh algorithm oracle replied:" output)
+ (not (string-contains? output "unknown key type"))))))
+
+(define keys
+ '(("dsa" "9a:e1:f1:5f:46:ea:a5:06:e1:e2:f8:38:8e:06:54:58")
+ ("rsa" "c9:85:b5:55:00:84:a9:82:5a:df:d6:62:1b:5a:28:22")
+ ("ecdsa" "93:37:30:a6:4e:e7:6a:22:79:77:8e:bf:ed:14:e9:8e")
+ ("ed25519" "08:df:be:af:d2:f5:32:20:3a:1c:56:06:be:31:0f:bf")))
+
+(for-each-p'
+ "Importing ssh keys..."
+ (lambda (key)
+ (let ((file (path-join (in-srcdir "tests" "openpgp" "samplekeys")
+ (string-append "ssh-" (car key) ".key")))
+ (hash (cadr key)))
+ ;; We pipe the key to ssh-add so that it won't complain about
+ ;; file's permissions.
+ (pipe:do
+ (pipe:open file (logior O_RDONLY O_BINARY))
+ (pipe:spawn `(,SSH-ADD -)))
+ (unless (string-contains? (call-popen `(,SSH-ADD -l "-E" md5) "") hash)
+ (fail "key not added"))))
+ car (filter (lambda (x) (ssh-supports? (car x))) keys))
+
+(info "Checking for issue2316...")
+(unlink (path-join GNUPGHOME "sshcontrol"))
+(pipe:do
+ (pipe:open (path-join (in-srcdir "tests" "openpgp" "samplekeys")
+ (string-append "ssh-rsa.key"))
+ (logior O_RDONLY O_BINARY))
+ (pipe:spawn `(,SSH-ADD -)))
+(unless
+ (string-contains? (call-popen `(,SSH-ADD -l "-E" md5) "")
+ "c9:85:b5:55:00:84:a9:82:5a:df:d6:62:1b:5a:28:22")
+ (fail "known private key not (re-)added to sshcontrol"))
diff --git a/tests/openpgp/tofu.scm b/tests/openpgp/tofu.scm
new file mode 100755
index 0000000..cd4b4c7
--- /dev/null
+++ b/tests/openpgp/tofu.scm
@@ -0,0 +1,420 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(load (with-path "time.scm"))
+(setup-environment)
+
+(define GPGTIME 1480943782)
+
+;; Generate a --faked-system-time parameter for a particular offset.
+(define (faketime delta)
+ (string-append "--faked-system-time=" (number->string (+ GPGTIME delta))))
+
+;; Redefine GPG without --always-trust and a fixed time.
+(define GPG `(,(tool 'gpg) --no-permission-warning ,(faketime 0)))
+
+(catch (skip "Tofu not supported")
+ (call-check `(,@GPG --trust-model=tofu --list-config)))
+
+(let ((trust-model (gpg-config 'gpg "trust-model")))
+ (trust-model::update "tofu"))
+
+(define KEYS '("1C005AF3" "BE04EB2B" "B662E42F"))
+
+;; Import the test keys.
+(for-each (lambda (keyid)
+ (call-check `(,@GPG --import
+ ,(in-srcdir "tests" "openpgp" "tofu" "conflicting"
+ (string-append keyid ".gpg"))))
+ (catch (fail "Missing key" keyid)
+ (call-check `(,@GPG --list-keys ,keyid))))
+ KEYS)
+
+;; Get tofu policy for KEYID. Any remaining arguments are simply
+;; passed to GPG.
+;;
+;; This function only supports keys with a single user id.
+(define (getpolicy keyid . args)
+ (let ((policy
+ (list-ref (assoc "tfs" (gpg-with-colons
+ `(--with-tofu-info
+ ,@args
+ --list-keys ,keyid))) 5)))
+ (unless (member policy '("auto" "good" "unknown" "bad" "ask"))
+ (fail "Bad policy:" policy))
+ policy))
+
+;; Check that KEYID's tofu policy matches EXPECTED-POLICY. Any
+;; remaining arguments are simply passed to GPG.
+;;
+;; This function only supports keys with a single user id.
+(define (checkpolicy keyid expected-policy . args)
+ (let ((policy (apply getpolicy `(,keyid ,@args))))
+ (unless (string=? policy expected-policy)
+ (fail keyid ": Expected policy to be" expected-policy
+ "but got" policy))))
+
+;; Set key KEYID's policy to POLICY. Any remaining arguments are
+;; passed as options to gpg.
+(define (setpolicy keyid policy . args)
+ (call-check `(,@GPG ,@args
+ --tofu-policy ,policy ,keyid)))
+
+(info "Checking tofu policies and trust...")
+
+;; Carefully remove the TOFU db.
+(catch '() (unlink (path-join GNUPGHOME "tofu.db")))
+
+;; Verify a message. There should be no conflict and the trust
+;; policy should be set to auto.
+(call-check `(,@GPG --verify ,(in-srcdir "tests" "openpgp" "tofu" "conflicting" "1C005AF3-1.txt")))
+
+(checkpolicy "1C005AF3" "auto")
+;; Check default trust.
+(checktrust "1C005AF3" "m")
+
+;; Trust should be derived lazily. Thus, if the policy is set to
+;; auto and we change --tofu-default-policy, then the trust should
+;; change as well. Try it.
+(checktrust "1C005AF3" "f" '--tofu-default-policy=good)
+(checktrust "1C005AF3" "-" '--tofu-default-policy=unknown)
+(checktrust "1C005AF3" "n" '--tofu-default-policy=bad)
+(checktrust "1C005AF3" "q" '--tofu-default-policy=ask)
+
+;; Change the policy to something other than auto and make sure the
+;; policy and the trust are correct.
+(for-each-p
+ "Setting a fixed policy..."
+ (lambda (policy)
+ (let ((expected-trust
+ (cond
+ ((string=? "good" policy) "f")
+ ((string=? "unknown" policy) "-")
+ (else "n"))))
+ (setpolicy "1C005AF3" policy)
+
+ ;; Since we have a fixed policy, the trust level shouldn't
+ ;; change if we change the default policy.
+ (for-each-p
+ ""
+ (lambda (default-policy)
+ (checkpolicy "1C005AF3" policy
+ '--tofu-default-policy default-policy)
+ (checktrust "1C005AF3" expected-trust
+ '--tofu-default-policy default-policy))
+ '("auto" "good" "unknown" "bad" "ask"))))
+ '("good" "unknown" "bad"))
+
+;; At the end, 1C005AF3's policy should be bad.
+(checkpolicy "1C005AF3" "bad")
+
+;; 1C005AF3 and BE04EB2B conflict. A policy setting of "auto"
+;; (BE04EB2B's state) will result in an effective policy of ask. But,
+;; a policy setting of "bad" will result in an effective policy of
+;; bad.
+(setpolicy "BE04EB2B" "auto")
+(checkpolicy "BE04EB2B" "ask")
+(checkpolicy "1C005AF3" "bad")
+
+;; 1C005AF3, B662E42F, and BE04EB2B conflict. We change BE04EB2B's
+;; policy to auto and leave 1C005AF3's policy at bad. This conflict
+;; should cause BE04EB2B's effective policy to be ask (since it is
+;; auto), but not affect 1C005AF3's policy.
+(setpolicy "BE04EB2B" "auto")
+(checkpolicy "BE04EB2B" "ask")
+(call-check `(,@GPG --verify ,(in-srcdir "tests" "openpgp" "tofu" "conflicting" "B662E42F-1.txt")))
+(checkpolicy "BE04EB2B" "ask")
+(checkpolicy "1C005AF3" "bad")
+(checkpolicy "B662E42F" "ask")
+
+;; Check that the stats are emitted correctly.
+
+(display "Checking TOFU stats...\n")
+
+(define (check-counts keyid expected-sigs expected-sig-days
+ expected-encs expected-enc-days . args)
+ (let*
+ ((tfs (assoc "tfs"
+ (gpg-with-colons
+ `(--with-tofu-info ,@args --list-keys ,keyid))))
+ (sigs (string->number (list-ref tfs 3)))
+ (sig-days (string->number (list-ref tfs 11)))
+ (encs (string->number (list-ref tfs 4)))
+ (enc-days (string->number (list-ref tfs 12)))
+ )
+ ; (display keyid) (display ": ") (display tfs) (display "\n")
+ (unless (= sigs expected-sigs)
+ (fail keyid ": # signatures (" sigs ") does not match expected"
+ "# signatures (" expected-sigs ").\n"))
+ (unless (= sig-days expected-sig-days)
+ (fail keyid ": # signature days (" sig-days ")"
+ "does not match expected"
+ "# signature days (" expected-sig-days ").\n"))
+ (unless (= encs expected-encs)
+ (fail keyid ": # encryptions (" encs ") does not match expected"
+ "# encryptions (" expected-encs ").\n"))
+ (unless (= enc-days expected-enc-days)
+ (fail keyid ": # encryption days (" encs ")"
+ "does not match expected"
+ "# encryption days (" expected-enc-days ").\n"))
+ ))
+
+;; Carefully remove the TOFU db.
+(catch '() (unlink (path-join GNUPGHOME "tofu.db")))
+
+(check-counts "1C005AF3" 0 0 0 0)
+(check-counts "BE04EB2B" 0 0 0 0)
+(check-counts "B662E42F" 0 0 0 0)
+
+;; Verify a message. The signature count should increase by 1.
+(call-check `(,@GPG --verify ,(in-srcdir "tests" "openpgp" "tofu" "conflicting" "1C005AF3-1.txt")))
+
+(check-counts "1C005AF3" 1 1 0 0)
+
+;; Verify the same message. The signature count should remain the
+;; same.
+(call-check `(,@GPG --verify ,(in-srcdir "tests" "openpgp" "tofu" "conflicting" "1C005AF3-1.txt")))
+(check-counts "1C005AF3" 1 1 0 0)
+
+;; Verify another message.
+(call-check `(,@GPG --verify ,(in-srcdir "tests" "openpgp" "tofu" "conflicting" "1C005AF3-2.txt")))
+(check-counts "1C005AF3" 2 1 0 0)
+
+;; Verify another message.
+(call-check `(,@GPG --verify ,(in-srcdir "tests" "openpgp" "tofu" "conflicting" "1C005AF3-3.txt")))
+(check-counts "1C005AF3" 3 1 0 0)
+
+;; Verify a message from a different sender. The signature count
+;; should increase by 1 for that key.
+(call-check `(,@GPG --verify ,(in-srcdir "tests" "openpgp" "tofu" "conflicting" "BE04EB2B-1.txt")))
+(check-counts "1C005AF3" 3 1 0 0)
+(check-counts "BE04EB2B" 1 1 0 0)
+(check-counts "B662E42F" 0 0 0 0)
+
+;; Verify another message on a new day. (Recall: we are interested in
+;; when the message was first verified, not when the signer claimed
+;; that it was signed.)
+(call-check `(,@GPG ,(faketime (days->seconds 2))
+ --verify ,(in-srcdir "tests" "openpgp" "tofu" "conflicting" "1C005AF3-4.txt")))
+(check-counts "1C005AF3" 4 2 0 0)
+(check-counts "BE04EB2B" 1 1 0 0)
+(check-counts "B662E42F" 0 0 0 0)
+
+;; And another.
+(call-check `(,@GPG ,(faketime (days->seconds 2))
+ --verify ,(in-srcdir "tests" "openpgp" "tofu" "conflicting" "1C005AF3-5.txt")))
+(check-counts "1C005AF3" 5 2 0 0)
+(check-counts "BE04EB2B" 1 1 0 0)
+(check-counts "B662E42F" 0 0 0 0)
+
+;; Another, but for a different key.
+(call-check `(,@GPG ,(faketime (days->seconds 2))
+ --verify ,(in-srcdir "tests" "openpgp" "tofu" "conflicting" "BE04EB2B-2.txt")))
+(check-counts "1C005AF3" 5 2 0 0)
+(check-counts "BE04EB2B" 2 2 0 0)
+(check-counts "B662E42F" 0 0 0 0)
+
+;; And add a third day.
+(call-check `(,@GPG ,(faketime (days->seconds 4))
+ --verify ,(in-srcdir "tests" "openpgp" "tofu" "conflicting" "BE04EB2B-3.txt")))
+(check-counts "1C005AF3" 5 2 0 0)
+(check-counts "BE04EB2B" 3 3 0 0)
+(check-counts "B662E42F" 0 0 0 0)
+
+(call-check `(,@GPG ,(faketime (days->seconds 4))
+ --verify ,(in-srcdir "tests" "openpgp" "tofu" "conflicting" "BE04EB2B-4.txt")))
+(check-counts "1C005AF3" 5 2 0 0)
+(check-counts "BE04EB2B" 4 3 0 0)
+(check-counts "B662E42F" 0 0 0 0)
+
+;; Check that we detect the following attack:
+;;
+;; Alice and Bob each have a key and cross sign them. Bob then adds a
+;; new user id, "Alice". TOFU should now detect a conflict, because
+;; Alice only signed Bob's "Bob" user id.
+
+(display "Checking cross sigs...\n")
+(define GPG `(,(tool 'gpg) --no-permission-warning
+ --faked-system-time=1476304861))
+
+;; Carefully remove the TOFU db.
+(catch '() (unlink (path-join GNUPGHOME "tofu.db")))
+
+(define DIR "tofu/cross-sigs")
+;; The test keys.
+(define KEYA "1938C3A0E4674B6C217AC0B987DB2814EC38277E")
+(define KEYB "DC463A16E42F03240D76E8BA8B48C6BD871C2247")
+(define KEYIDA (substring KEYA (- (string-length KEYA) 8)))
+(define KEYIDB (substring KEYB (- (string-length KEYB) 8)))
+
+(define (verify-messages)
+ (for-each
+ (lambda (key)
+ (for-each
+ (lambda (i)
+ (let ((fn (in-srcdir "tests" "openpgp" DIR (string-append key "-" i ".txt"))))
+ (call-check `(,@GPG --verify ,fn))))
+ (list "1" "2")))
+ (list KEYIDA KEYIDB)))
+
+;; Import the public keys.
+(display " > Two keys. ")
+(call-check `(,@GPG --import ,(in-srcdir "tests" "openpgp" DIR (string-append KEYIDA "-1.gpg"))))
+(call-check `(,@GPG --import ,(in-srcdir "tests" "openpgp" DIR (string-append KEYIDB "-1.gpg"))))
+;; Make sure the tofu engine registers the keys.
+(verify-messages)
+(display "<\n")
+
+;; Since there is no conflict, the policy should be auto.
+(checkpolicy KEYA "auto")
+(checkpolicy KEYB "auto")
+
+;; Import the cross sigs.
+(display " > Adding cross signatures. ")
+(call-check `(,@GPG --import ,(in-srcdir "tests" "openpgp" DIR (string-append KEYIDA "-2.gpg"))))
+(call-check `(,@GPG --import ,(in-srcdir "tests" "openpgp" DIR (string-append KEYIDB "-2.gpg"))))
+(verify-messages)
+(display "<\n")
+
+;; There is still no conflict, so the policy shouldn't have changed.
+(checkpolicy KEYA "auto")
+(checkpolicy KEYB "auto")
+
+;; Import the conflicting user id.
+(display " > Adding conflicting user id. ")
+(call-check `(,@GPG --import ,(in-srcdir "tests" "openpgp" DIR (string-append KEYIDB "-3.gpg"))))
+(verify-messages)
+(display "<\n")
+
+(checkpolicy KEYA "ask")
+(checkpolicy KEYB "ask")
+
+;; Import Alice's signature on the conflicting user id. Since there
+;; is now a cross signature, we should revert to the default policy.
+(display " > Adding cross signature on user id. ")
+(call-check `(,@GPG --import ,(in-srcdir "tests" "openpgp" DIR (string-append KEYIDB "-4.gpg"))))
+(verify-messages)
+(display "<\n")
+
+(checkpolicy KEYA "auto")
+(checkpolicy KEYB "auto")
+
+;; Remove the keys.
+(call-check `(,@GPG --delete-key ,KEYA))
+(call-check `(,@GPG --delete-key ,KEYB))
+
+
+;; Check that we detect the following attack:
+;;
+;; Alice has an ultimately trusted key and she signs Bob's key. Then
+;; Bob adds a new user id, "Alice". TOFU should now detect a
+;; conflict, because Alice only signed Bob's "Bob" user id.
+;;
+;;
+;; The Alice key:
+;; pub rsa2048 2016-10-11 [SC]
+;; 1938C3A0E4674B6C217AC0B987DB2814EC38277E
+;; uid [ultimate] Spy Cow <spy@cow.com>
+;; sub rsa2048 2016-10-11 [E]
+;;
+;; The Bob key:
+;;
+;; pub rsa2048 2016-10-11 [SC]
+;; DC463A16E42F03240D76E8BA8B48C6BD871C2247
+;; uid [ full ] Spy R. Cow <spy@cow.com>
+;; uid [ full ] Spy R. Cow <spy@cow.de>
+;; sub rsa2048 2016-10-11 [E]
+
+(display "Checking UTK sigs...\n")
+(define GPG `(,(tool 'gpg) --no-permission-warning
+ --faked-system-time=1476304861))
+
+;; Carefully remove the TOFU db.
+(catch '() (unlink (path-join GNUPGHOME "tofu.db")))
+
+(define DIR "tofu/cross-sigs")
+;; The test keys.
+(define KEYA "1938C3A0E4674B6C217AC0B987DB2814EC38277E")
+(define KEYB "DC463A16E42F03240D76E8BA8B48C6BD871C2247")
+(define KEYIDA (substring KEYA (- (string-length KEYA) 8)))
+(define KEYIDB (substring KEYB (- (string-length KEYB) 8)))
+
+(define (verify-messages)
+ (for-each
+ (lambda (key)
+ (for-each
+ (lambda (i)
+ (let ((fn (in-srcdir "tests" "openpgp" DIR (string-append key "-" i ".txt"))))
+ (call-check `(,@GPG --verify ,fn))))
+ (list "1" "2")))
+ (list KEYIDA KEYIDB)))
+
+;; Import the public keys.
+(display " > Two keys. ")
+(call-check `(,@GPG --import ,(in-srcdir "tests" "openpgp" DIR (string-append KEYIDA "-1.gpg"))))
+(call-check `(,@GPG --import ,(in-srcdir "tests" "openpgp" DIR (string-append KEYIDB "-1.gpg"))))
+(display "<\n")
+
+(checkpolicy KEYA "auto")
+(checkpolicy KEYB "auto")
+
+;; Import the cross sigs.
+(display " > Adding cross signatures. ")
+(call-check `(,@GPG --import ,(in-srcdir "tests" "openpgp" DIR (string-append KEYIDA "-2.gpg"))))
+(call-check `(,@GPG --import ,(in-srcdir "tests" "openpgp" DIR (string-append KEYIDB "-2.gpg"))))
+(display "<\n")
+
+(checkpolicy KEYA "auto")
+(checkpolicy KEYB "auto")
+
+;; Make KEYA ultimately trusted.
+(display (string-append " > Marking " KEYA " as ultimately trusted. "))
+(pipe:do
+ (pipe:echo (string-append KEYA ":6:\n"))
+ (pipe:gpg `(--import-ownertrust)))
+(display "<\n")
+
+;; An ultimately trusted key's policy is good.
+(checkpolicy KEYA "good")
+;; A key signed by a UTK for which there is no policy gets the default
+;; policy of good.
+(checkpolicy KEYB "good")
+
+;; Import the conflicting user id.
+(display " > Adding conflicting user id. ")
+(call-check `(,@GPG --import ,(in-srcdir "tests" "openpgp" DIR (string-append KEYIDB "-3.gpg"))))
+(verify-messages)
+(display "<\n")
+
+(checkpolicy KEYA "good")
+(checkpolicy KEYB "ask")
+
+;; Import Alice's signature on the conflicting user id.
+(display " > Adding cross signature on user id. ")
+(call-check `(,@GPG --import ,(in-srcdir "tests" "openpgp" DIR (string-append KEYIDB "-4.gpg"))))
+(verify-messages)
+(display "<\n")
+
+(checkpolicy KEYA "good")
+(checkpolicy KEYB "good")
+
+;; Remove the keys.
+(call-check `(,@GPG --delete-key ,KEYA))
+(call-check `(,@GPG --delete-key ,KEYB))
diff --git a/tests/openpgp/tofu/conflicting/1C005AF3-1.txt b/tests/openpgp/tofu/conflicting/1C005AF3-1.txt
new file mode 100644
index 0000000..dba581d
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/1C005AF3-1.txt
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/1C005AF3-2.txt b/tests/openpgp/tofu/conflicting/1C005AF3-2.txt
new file mode 100644
index 0000000..fde9fb8
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/1C005AF3-2.txt
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/1C005AF3-3.txt b/tests/openpgp/tofu/conflicting/1C005AF3-3.txt
new file mode 100644
index 0000000..e6aa4ac
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/1C005AF3-3.txt
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/1C005AF3-4.txt b/tests/openpgp/tofu/conflicting/1C005AF3-4.txt
new file mode 100644
index 0000000..6a14891
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/1C005AF3-4.txt
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/1C005AF3-5.txt b/tests/openpgp/tofu/conflicting/1C005AF3-5.txt
new file mode 100644
index 0000000..12fb5fb
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/1C005AF3-5.txt
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/1C005AF3-secret.gpg b/tests/openpgp/tofu/conflicting/1C005AF3-secret.gpg
new file mode 100644
index 0000000..5f1e78a
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/1C005AF3-secret.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/1C005AF3.gpg b/tests/openpgp/tofu/conflicting/1C005AF3.gpg
new file mode 100644
index 0000000..7a75011
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/1C005AF3.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/B662E42F-1.txt b/tests/openpgp/tofu/conflicting/B662E42F-1.txt
new file mode 100644
index 0000000..c39056c
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/B662E42F-1.txt
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/B662E42F-2.txt b/tests/openpgp/tofu/conflicting/B662E42F-2.txt
new file mode 100644
index 0000000..a96ef9f
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/B662E42F-2.txt
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/B662E42F-3.txt b/tests/openpgp/tofu/conflicting/B662E42F-3.txt
new file mode 100644
index 0000000..2e6e81b
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/B662E42F-3.txt
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/B662E42F-4.txt b/tests/openpgp/tofu/conflicting/B662E42F-4.txt
new file mode 100644
index 0000000..470882f
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/B662E42F-4.txt
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/B662E42F-5.txt b/tests/openpgp/tofu/conflicting/B662E42F-5.txt
new file mode 100644
index 0000000..21d54bc
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/B662E42F-5.txt
@@ -0,0 +1 @@
+%[}I i\,  b,&khӌ)eech&q0l;Sɵ`K>}iw5?VF+' |]$/jmJߖTjY<i6%|aGVkg4e<akB UoffZ<U[hJen뤙 f~[dm"v?P3}=}#"^j-Tҁ՜+/q=&>̬%kzNlʳמ:7z\o޵sJs1 \ No newline at end of file
diff --git a/tests/openpgp/tofu/conflicting/B662E42F-secret.gpg b/tests/openpgp/tofu/conflicting/B662E42F-secret.gpg
new file mode 100644
index 0000000..7362ded
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/B662E42F-secret.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/B662E42F.gpg b/tests/openpgp/tofu/conflicting/B662E42F.gpg
new file mode 100644
index 0000000..6c07520
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/B662E42F.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/BE04EB2B-1.txt b/tests/openpgp/tofu/conflicting/BE04EB2B-1.txt
new file mode 100644
index 0000000..1b3de47
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/BE04EB2B-1.txt
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/BE04EB2B-2.txt b/tests/openpgp/tofu/conflicting/BE04EB2B-2.txt
new file mode 100644
index 0000000..f4f5487
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/BE04EB2B-2.txt
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/BE04EB2B-3.txt b/tests/openpgp/tofu/conflicting/BE04EB2B-3.txt
new file mode 100644
index 0000000..7451073
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/BE04EB2B-3.txt
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/BE04EB2B-4.txt b/tests/openpgp/tofu/conflicting/BE04EB2B-4.txt
new file mode 100644
index 0000000..f15496d
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/BE04EB2B-4.txt
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/BE04EB2B-5.txt b/tests/openpgp/tofu/conflicting/BE04EB2B-5.txt
new file mode 100644
index 0000000..39078f1
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/BE04EB2B-5.txt
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/BE04EB2B-secret.gpg b/tests/openpgp/tofu/conflicting/BE04EB2B-secret.gpg
new file mode 100644
index 0000000..5d393aa
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/BE04EB2B-secret.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/conflicting/BE04EB2B.gpg b/tests/openpgp/tofu/conflicting/BE04EB2B.gpg
new file mode 100644
index 0000000..787b238
--- /dev/null
+++ b/tests/openpgp/tofu/conflicting/BE04EB2B.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/871C2247-1.gpg b/tests/openpgp/tofu/cross-sigs/871C2247-1.gpg
new file mode 100644
index 0000000..f706f70
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/871C2247-1.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/871C2247-1.txt b/tests/openpgp/tofu/cross-sigs/871C2247-1.txt
new file mode 100644
index 0000000..0bdc1fc
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/871C2247-1.txt
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/871C2247-2.gpg b/tests/openpgp/tofu/cross-sigs/871C2247-2.gpg
new file mode 100644
index 0000000..0b2485f
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/871C2247-2.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/871C2247-2.txt b/tests/openpgp/tofu/cross-sigs/871C2247-2.txt
new file mode 100644
index 0000000..4d3aaaa
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/871C2247-2.txt
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/871C2247-3.gpg b/tests/openpgp/tofu/cross-sigs/871C2247-3.gpg
new file mode 100644
index 0000000..eb2c435
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/871C2247-3.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/871C2247-3.txt b/tests/openpgp/tofu/cross-sigs/871C2247-3.txt
new file mode 100644
index 0000000..9b2d49d
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/871C2247-3.txt
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/871C2247-4.gpg b/tests/openpgp/tofu/cross-sigs/871C2247-4.gpg
new file mode 100644
index 0000000..9c98ec1
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/871C2247-4.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/871C2247-secret.gpg b/tests/openpgp/tofu/cross-sigs/871C2247-secret.gpg
new file mode 100644
index 0000000..a87c61b
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/871C2247-secret.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/EC38277E-1.gpg b/tests/openpgp/tofu/cross-sigs/EC38277E-1.gpg
new file mode 100644
index 0000000..e6becec
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/EC38277E-1.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/EC38277E-1.txt b/tests/openpgp/tofu/cross-sigs/EC38277E-1.txt
new file mode 100644
index 0000000..92236be
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/EC38277E-1.txt
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/EC38277E-2.gpg b/tests/openpgp/tofu/cross-sigs/EC38277E-2.gpg
new file mode 100644
index 0000000..d26bd54
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/EC38277E-2.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/EC38277E-2.txt b/tests/openpgp/tofu/cross-sigs/EC38277E-2.txt
new file mode 100644
index 0000000..b4013d3
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/EC38277E-2.txt
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/EC38277E-3.txt b/tests/openpgp/tofu/cross-sigs/EC38277E-3.txt
new file mode 100644
index 0000000..9b2d49d
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/EC38277E-3.txt
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/EC38277E-secret.gpg b/tests/openpgp/tofu/cross-sigs/EC38277E-secret.gpg
new file mode 100644
index 0000000..1839e3a
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/EC38277E-secret.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/README b/tests/openpgp/tofu/cross-sigs/README
new file mode 100644
index 0000000..439962b
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/README
@@ -0,0 +1,79 @@
+# How I generate the keys and messages to verify:
+
+# Generate and export two non-conflicting keys.
+gpg --quick-gen-key 'Spy Cow <spy@cow.com>'
+gpg --quick-gen-key 'Spy R. Cow <spy@cow.de>'
+
+KEYIDA=1938C3A0E4674B6C217AC0B987DB2814EC38277E
+KEYIDB=DC463A16E42F03240D76E8BA8B48C6BD871C2247
+
+for KEYID in $KEYIDA $KEYIDB
+do
+ gpg --export $KEYID > tofu-$KEYID.gpg
+ gpg --export-secret-keys $KEYID > tofu-$KEYID-secret.gpg
+done
+
+# Sign some data.
+echo foo | gpg --default-key $KEYIDA -s > tofu-$KEYIDA-1.txt
+echo foo | gpg --default-key $KEYIDB -s > tofu-$KEYIDB-1.txt
+
+# Again, but with an issuer.
+echo foo | gpg --default-key "<spy@cow.com>" -s > tofu-$KEYIDA-2.txt
+echo foo | gpg --default-key "<spy@cow.de>" -s > tofu-$KEYIDB-2.txt
+
+# Have A sign B and vice versa.
+gpg --default-key $KEYIDA --quick-sign $KEYIDB
+gpg --default-key $KEYIDB --quick-sign $KEYIDA
+
+gpg --export $KEYIDA > tofu-$KEYIDA-2.gpg
+gpg --export $KEYIDB > tofu-$KEYIDB-2.gpg
+
+# Cause A and B to conflict.
+gpg --quick-adduid $KEYIDB 'Spy R. Cow <spy@cow.com>'
+gpg --export $KEYIDB > tofu-$KEYIDB-3.gpg
+
+echo foo | gpg --default-key "<spy@cow.com>" -s > tofu-$KEYIDA-3.txt
+echo foo | gpg --default-key "<spy@cow.com>" -s > tofu-$KEYIDB-3.txt
+
+# Have A sign B's conflicting user id.
+gpg --default-key $KEYIDA --quick-sign $KEYIDB
+gpg --export $KEYIDB > tofu-$KEYIDB-4.gpg
+
+exit 0
+
+# In a new directory (so the keys are not ultimately trusted).
+
+D=~/neal/work/gpg/test
+echo 'trust-model tofu+pgp' > gpg.conf
+gpg --import $D/tofu-$KEYIDA.gpg
+gpg --import $D/tofu-$KEYIDB.gpg
+gpg -k
+
+gpg --verify $D/tofu-$KEYIDA-1.txt
+gpg --verify $D/tofu-$KEYIDB-1.txt
+# With an issuer.
+gpg --verify $D/tofu-$KEYIDA-2.txt
+gpg --verify $D/tofu-$KEYIDB-2.txt
+
+# Import the cross signatures.
+gpg --import $D/tofu-$KEYIDA-2.gpg
+gpg --import $D/tofu-$KEYIDB-2.gpg
+gpg -k
+
+gpg --verify $D/tofu-$KEYIDA-1.txt
+gpg --verify $D/tofu-$KEYIDB-1.txt
+# With an issuer.
+gpg --verify $D/tofu-$KEYIDA-2.txt
+gpg --verify $D/tofu-$KEYIDB-2.txt
+
+
+gpg --status-fd=1 --batch --verify $D/tofu-$KEYIDA-3.txt | grep TRUST_UNDEFINED
+gpg --status-fd=1 --batch --verify $D/tofu-$KEYIDB-3.txt | grep TRUST_UNDEFINED
+
+# Import the conflicting user id.
+gpg --import $D/tofu-$KEYIDB-3.gpg
+gpg -k
+
+# Import the cross signature, which should remove the conflict.
+gpg --import $D/tofu-$KEYIDB-4.gpg
+gpg -k
diff --git a/tests/openpgp/trust-pgp-1.scm b/tests/openpgp/trust-pgp-1.scm
new file mode 100755
index 0000000..235cb55
--- /dev/null
+++ b/tests/openpgp/trust-pgp-1.scm
@@ -0,0 +1,76 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2017 Damien Goutte-Gattat
+;;
+;; This file is part of GnuPG.
+;;
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "trust-pgp" "common.scm"))
+
+(display "Checking basic WoT (classic trust model)...\n")
+
+(initscenario "scenario1")
+
+;; Check initial state.
+(checktrust BOBBY "f") ;; Directly signed by Alice's key.
+(checktrust CAROL "q") ;; Signed by Bobby, whose key has
+ ;; no explicit ownertrust.
+(checktrust DAVID "q") ;; Likewise.
+(checktrust FRANK "q") ;; Likewise.
+(checktrust GRACE "-") ;; Signed by the previous three keys;
+ ;; not evaluated since they are not valid.
+
+;; Let's trust Bobby.
+;; This should make Carol's, David's, and Frank's keys valid.
+(setownertrust BOBBY FULLTRUST)
+(updatetrustdb)
+(checktrust CAROL "f")
+(checktrust DAVID "f")
+(checktrust FRANK "f")
+(checktrust GRACE "q") ;; Now evaluated, but validity still unknown.
+
+;; Let's trust (marginally) Carol and David.
+;; This should not be enough to make Grace's key fully valid
+;; since marginals-needed defaults to 3.
+(setownertrust CAROL MARGINALTRUST)
+(setownertrust DAVID MARGINALTRUST)
+(updatetrustdb)
+(checktrust GRACE "m")
+
+;; Add marginal ownertrust to Frank's key.
+;; This should make Grace's key fully valid.
+(setownertrust FRANK MARGINALTRUST)
+(updatetrustdb)
+(checktrust GRACE "f")
+
+;; Now let's play with the length of certification chains.
+;; Setting max-cert-length to 2 should put Grace's key
+;; one step too far from Alice's key.
+(let ((max-cert-depth (gpg-config 'gpg "max-cert-depth")))
+ (max-cert-depth::update 2))
+(updatetrustdb)
+(checktrust GRACE "-")
+
+;; Raise the bar for assigning full validity.
+;; Bobby's key should be the only one retaining full validity.
+(let ((completes-needed (gpg-config 'gpg "completes-needed")))
+ (completes-needed::update 2))
+(updatetrustdb)
+(checktrust BOBBY "f")
+(checktrust CAROL "m")
+(checktrust DAVID "m")
+(checktrust FRANK "m")
+(checktrust GRACE "-")
diff --git a/tests/openpgp/trust-pgp-2.scm b/tests/openpgp/trust-pgp-2.scm
new file mode 100755
index 0000000..a56d0a9
--- /dev/null
+++ b/tests/openpgp/trust-pgp-2.scm
@@ -0,0 +1,39 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2017 Damien Goutte-Gattat
+;;
+;; This file is part of GnuPG.
+;;
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "trust-pgp" "common.scm"))
+
+(display "Checking WoT with trust signatures (PGP trust model)...\n")
+
+(initscenario "scenario2")
+
+(checktrust BOBBY "f") ;; Tsigned by Alice with trust=120.
+(checktrust CAROL "f") ;; Signed by Bobby, whose key should have full
+ ;; ownertrust due to the tsig.
+(checktrust DAVID "f") ;; Signed by Alice.
+(checktrust FRANK "q") ;; Tsigned by David, whose key has no ownertrust.
+(checktrust GRACE "-") ;; Signed by Frank.
+
+(setownertrust DAVID FULLTRUST)
+(updatetrustdb)
+(checktrust FRANK "f") ;; David's key has now full ownertrust.
+(checktrust GRACE "q") ;; David is not authorized to emit tsigs,
+ ;; so his tsig on Frank's key should be treated
+ ;; like a normal sig (confering no ownertrust).
diff --git a/tests/openpgp/trust-pgp-3.scm b/tests/openpgp/trust-pgp-3.scm
new file mode 100755
index 0000000..33832db
--- /dev/null
+++ b/tests/openpgp/trust-pgp-3.scm
@@ -0,0 +1,31 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2017 Damien Goutte-Gattat
+;;
+;; This file is part of GnuPG.
+;;
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "trust-pgp" "common.scm"))
+
+(display "Checking max depth of trust signature chains...\n")
+
+(initscenario "scenario3")
+
+(checktrust BOBBY "f") ;; Tsigned by Alice (level=2, trust=120).
+(checktrust CAROL "f") ;; Tsigned by Bobby (level=2, trust=120).
+(checktrust DAVID "f") ;; Tsigned by Carol (level=2, trust=120).
+(checktrust FRANK "q") ;; The tsig from Carol does not confer
+ ;; ownertrust to David's key (too deep).
diff --git a/tests/openpgp/trust-pgp-4.scm b/tests/openpgp/trust-pgp-4.scm
new file mode 100755
index 0000000..17746a5
--- /dev/null
+++ b/tests/openpgp/trust-pgp-4.scm
@@ -0,0 +1,37 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2017 Damien Goutte-Gattat
+;;
+;; This file is part of GnuPG.
+;;
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "trust-pgp" "common.scm"))
+
+(display "Checking trust signature with domain restrictions...\n")
+
+(initscenario "scenario4")
+
+(checktrust BOBBY "f") ;; Tsigned by Alice, allowed to sign for example.com.
+(checktrust CAROL "-") ;; Signed by Bobby, but the signature should be
+ ;; ignored since Carol has an address in example.net.
+
+(checktrust DAVID "f") ;; Tsigned by Alice, allowed to sign for example.net.
+(checktrust FRANK "-") ;; Tsignature from David should be ignored because
+ ;; Frank has an address in example.com.
+
+(checktrust HEIDI "f") ;; Tsigned by David, should be valid since Heidi
+ ;; has an address in example.org.
+(checktrust GRACE "f") ;; Signed by Heidi.
diff --git a/tests/openpgp/trust-pgp/alice.sec.asc b/tests/openpgp/trust-pgp/alice.sec.asc
new file mode 100644
index 0000000..1cdde46
--- /dev/null
+++ b/tests/openpgp/trust-pgp/alice.sec.asc
@@ -0,0 +1,11 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+lHcEWW2+WxMIKoZIzj0DAQcCAwQnUnqiwvOPU7gGepFTew8Fk5kmVexr+PvaqXgv
+9wKxNzZrs4GvamULk9pl2euwJGKPBRJRz8RSNpW6HIIzAPoOAAEAgOZk+WDjrmum
+0OygJdb6qJp27qsyXvMVZ8AGlsdYtUgS37QZQWxpY2UgPGFsaWNlQGV4YW1wbGUu
+b3JnPoiQBBMTCAA4FiEE/Zsg3TyYEj7ur4zFG6QVONLmVrUFAlltvlsCGwMFCwkI
+BwIGFQgJCgsCBBYCAwECHgECF4AACgkQG6QVONLmVrU7PAEAvOqeIRMiJ8Ne0tz+
+K1aRz/np/umCQxO8ddm9mnr4M7EA/1z4YdD06wJXp4RXUI0G2QOHTY+QXMShCFrp
+ySArWQqN
+=3+Iz
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp/trust-pgp/bobby.sec.asc b/tests/openpgp/trust-pgp/bobby.sec.asc
new file mode 100644
index 0000000..2164b5d
--- /dev/null
+++ b/tests/openpgp/trust-pgp/bobby.sec.asc
@@ -0,0 +1,11 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+lHcEWW3WihMIKoZIzj0DAQcCAwTtUYI84wfNPCwa/r2ke7tXz0uv/En9LQZbW0QE
+nzHigEvMXLfyjfjCf5tQ2eVbKLbABxtKwDtC2bv8dMcmgqd/AAEA6EzyQYtLOL9v
+4SErBRic7MmQfxFbEJIQSu2vtbWos/0QFLQZQm9iYnkgPGJvYmJ5QGV4YW1wbGUu
+Y29tPoiQBBMTCAA4FiEETT9Z9NgDD9LYRK/rpbrD7RJcyuUFAllt1ooCGwMFCwkI
+BwIGFQgJCgsCBBYCAwECHgECF4AACgkQpbrD7RJcyuWUjgEA9UreuOxgDzhSCGAQ
+5GtxBiXkmp/IuH/rvNI8qZaVnoIBAPs/VUgy3eySjF6g9wf/UzvqwUdtoaYvkyC2
+a25O7Lxc
+=76RO
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp/trust-pgp/carol.sec.asc b/tests/openpgp/trust-pgp/carol.sec.asc
new file mode 100644
index 0000000..d366f3f
--- /dev/null
+++ b/tests/openpgp/trust-pgp/carol.sec.asc
@@ -0,0 +1,11 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+lHcEWW3WrxMIKoZIzj0DAQcCAwS4HzEJ0YwXZ1SWciHOmWdfnESTvwC3Zb/sWRu8
+zdIeZzxAwu8lYQaDq/eOgKeXQVW5gxkQG5rCWUazbG+gCBEIAAEA2QzHlkxFJkTg
+QvZuimqU0AySYsleRUaO9B9UARiUbOYOwrQZQ2Fyb2wgPGNhcm9sQGV4YW1wbGUu
+bmV0PoiQBBMTCAA4FiEEbGJzXkVMzdefpspgEHkROuwSgv0FAllt1q8CGwMFCwkI
+BwIGFQgJCgsCBBYCAwECHgECF4AACgkQEHkROuwSgv3MygD+KdusoDvz7WZbsjjB
+WI/HLhWfWfXsoAR9mN/5rZ94HDgA/1VqbvUcM+vPU62g7/0qoGqWCda3SURB6263
+Kirbk6hY
+=wkQ4
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp/trust-pgp/common.scm b/tests/openpgp/trust-pgp/common.scm
new file mode 100644
index 0000000..2a545e8
--- /dev/null
+++ b/tests/openpgp/trust-pgp/common.scm
@@ -0,0 +1,66 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2017 Damien Goutte-Gattat
+;;
+;; This file is part of GnuPG.
+;;
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+
+;; Redefine GPG without --always-trust.
+(define GPG `(,(tool 'gpg)))
+
+;; Helper constants for setownertrust.
+(define MARGINALTRUST "4")
+(define FULLTRUST "5")
+(define ULTIMATETRUST "6")
+
+;; Assign OWNERTRUST to the key identified by the provided
+;; fingerprint KEYFPR.
+(define (setownertrust keyfpr ownertrust)
+ (pipe:do
+ (pipe:echo (string-append keyfpr ":" ownertrust ":\n"))
+ (pipe:gpg `(--import-ownertrust))))
+
+;; Force a trustdb update.
+(define (updatetrustdb)
+ (call-check `(,@GPG --check-trustdb --yes)))
+
+;; IDs of all the keys involved in those tests.
+(define ALICE "FD9B20DD3C98123EEEAF8CC51BA41538D2E656B5")
+(define BOBBY "4D3F59F4D8030FD2D844AFEBA5BAC3ED125CCAE5")
+(define CAROL "6C62735E454CCDD79FA6CA601079113AEC1282FD")
+(define DAVID "A0607635198CABA2C467FAA64CE5BB42E3984000")
+(define FRANK "CE1A0E07CF8A20CBF8DC47D6DB9017DBAE6CD0EF")
+(define GRACE "B935F4B8DA009AFBCCDD41386653A183007F8345")
+(define HEIDI "0389C0B7990E10520B334F23756F1571EDA9184B")
+
+;; Initialize a given scenario.
+;; NAME should be the basename of the scenario file
+;; in this directory.
+(define (initscenario name)
+ (setup-environment)
+ ;; Make sure we are using the PGP trust model. This may no
+ ;; be the default model in the future.
+ (let ((trust-model (gpg-config 'gpg "trust-model")))
+ (trust-model::update "pgp"))
+ ;; Load the scenario's public keys.
+ (call-check `(,@GPG --import
+ ,(in-srcdir "tests" "openpgp" "trust-pgp"
+ (string-append name ".asc"))))
+ ;; Use Alice's key as root for all trust evaluations.
+ (setownertrust ALICE ULTIMATETRUST)
+ (updatetrustdb))
diff --git a/tests/openpgp/trust-pgp/david.sec.asc b/tests/openpgp/trust-pgp/david.sec.asc
new file mode 100644
index 0000000..06c4e83
--- /dev/null
+++ b/tests/openpgp/trust-pgp/david.sec.asc
@@ -0,0 +1,11 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+lHcEWW3WzRMIKoZIzj0DAQcCAwQrTeILyHVpkkDsAyAlY7wz0PYjG48ShCYeTX2z
+5f2bLxZGeepQeMiOXznPvCwRNMNpr63048+LGqu34Q9di5tvAAD9HITG0iG5SzeW
+cGMfhzGuXEn2P+9arb0OttTUcj+eGBIP8bQZRGF2aWQgPGRhdmlkQGV4YW1wbGUu
+b3JnPoiQBBMTCAA4FiEEoGB2NRmMq6LEZ/qmTOW7QuOYQAAFAllt1s0CGwMFCwkI
+BwIGFQgJCgsCBBYCAwECHgECF4AACgkQTOW7QuOYQAAJtAD+JxiDZttAb51FjB5o
+J1BksmzIrgL6ouorbLLRjVyk7rkA/0JqyLhh1K3vn4rYDbuKtvQAcfQbCndzwF9X
+uGQ/7gbS
+=EC4L
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp/trust-pgp/frank.sec.asc b/tests/openpgp/trust-pgp/frank.sec.asc
new file mode 100644
index 0000000..50235de
--- /dev/null
+++ b/tests/openpgp/trust-pgp/frank.sec.asc
@@ -0,0 +1,11 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+lHcEWW3W3RMIKoZIzj0DAQcCAwQs0QS2PEUXhpmsPlaTFOsXd8AoYqpa6xcc0+AE
+Mck1EzlqRlxeibvYeh/+yxjl18Ouww/BERB+PcoABXp00zXzAAD+Oybk8/6x5nc8
+ZNHkRIbfHW8oKh7jxbpob9X7QIfBpf8TcbQZRnJhbmsgPGZyYW5rQGV4YW1wbGUu
+Y29tPoiQBBMTCAA4FiEEzhoOB8+KIMv43EfW25AX265s0O8FAllt1t0CGwMFCwkI
+BwIGFQgJCgsCBBYCAwECHgECF4AACgkQ25AX265s0O+nDQD/RplCmAPQgMejhs2/
+YmOqWrekyd4IWNj9zyI2n228WXYBAJ1/Wf1vBviOEqzs7t+C0iBExxJXViPlG0nN
+Z9aoiX1G
+=vnHF
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp/trust-pgp/grace.sec.asc b/tests/openpgp/trust-pgp/grace.sec.asc
new file mode 100644
index 0000000..23ebd71
--- /dev/null
+++ b/tests/openpgp/trust-pgp/grace.sec.asc
@@ -0,0 +1,11 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+lHcEWW3W8RMIKoZIzj0DAQcCAwRTGb7wRrdPa+mXxUNJoYgWbKfMDQH9M1H366PQ
+ga8L32TYccFzyCD8DuRYOQxzhnCtSHtdzK4QAwwGLaJV6GRjAAEAzBLT+dB5ga7S
+Lh7PepOB9yObDHrHAvXGXg9AUvEm3ZkQ6bQZR3JhY2UgPGdyYWNlQGV4YW1wbGUu
+bmV0PoiQBBMTCAA4FiEEuTX0uNoAmvvM3UE4ZlOhgwB/g0UFAllt1vECGwMFCwkI
+BwIGFQgJCgsCBBYCAwECHgECF4AACgkQZlOhgwB/g0W2AAD+KmW2DQALWTnsVnL/
+QKdJ1J8DsaR1l+y2h7FUYuFttQsBALZYs2vUwOVBnAYyqbHogqgbPSxKRXeAxNqo
+epx6csv+
+=05c1
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp/trust-pgp/heidi.sec.asc b/tests/openpgp/trust-pgp/heidi.sec.asc
new file mode 100644
index 0000000..f650d1a
--- /dev/null
+++ b/tests/openpgp/trust-pgp/heidi.sec.asc
@@ -0,0 +1,11 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+lHcEWW3XBxMIKoZIzj0DAQcCAwSINFpTZUYnxDDj3k16ljZIt58rh3cuUNIvUcqR
+zR9kdlmudQTaf1zUsW6F3r+t91t88kaA2Fcci3wkU0CAob0WAAD/eTlMM3JTEF6K
+yh8gxk1+mXRVUAmcGwr+1PzC3nzJAkgPALQZSGVpZGkgPGhlaWRpQGV4YW1wbGUu
+b3JnPoiQBBMTCAA4FiEEA4nAt5kOEFILM08jdW8Vce2pGEsFAllt1wcCGwMFCwkI
+BwIGFQgJCgsCBBYCAwECHgECF4AACgkQdW8Vce2pGEtwXAD/SVyIRiGnYPkqBVqG
+fI2MlTgN8+uirur2JdkcPoylCEMA/j3OeLRRT1docnEnvST1srmlXxZTbNUclnAl
+a2OZd7ME
+=1goe
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/openpgp/trust-pgp/scenario1.asc b/tests/openpgp/trust-pgp/scenario1.asc
new file mode 100644
index 0000000..82fee76
--- /dev/null
+++ b/tests/openpgp/trust-pgp/scenario1.asc
@@ -0,0 +1,75 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW2+WxMIKoZIzj0DAQcCAwQnUnqiwvOPU7gGepFTew8Fk5kmVexr+PvaqXgv
+9wKxNzZrs4GvamULk9pl2euwJGKPBRJRz8RSNpW6HIIzAPoOtBlBbGljZSA8YWxp
+Y2VAZXhhbXBsZS5vcmc+iJAEExMIADgWIQT9myDdPJgSPu6vjMUbpBU40uZWtQUC
+WW2+WwIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRAbpBU40uZWtTs8AQC8
+6p4hEyInw17S3P4rVpHP+en+6YJDE7x12b2aevgzsQD/XPhh0PTrAlenhFdQjQbZ
+A4dNj5BcxKEIWunJICtZCo0=
+=rf4w
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3WihMIKoZIzj0DAQcCAwTtUYI84wfNPCwa/r2ke7tXz0uv/En9LQZbW0QE
+nzHigEvMXLfyjfjCf5tQ2eVbKLbABxtKwDtC2bv8dMcmgqd/tBlCb2JieSA8Ym9i
+YnlAZXhhbXBsZS5jb20+iJAEExMIADgWIQRNP1n02AMP0thEr+ulusPtElzK5QUC
+WW3WigIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRClusPtElzK5ZSOAQD1
+St647GAPOFIIYBDka3EGJeSan8i4f+u80jyplpWeggEA+z9VSDLd7JKMXqD3B/9T
+O+rBR22hpi+TILZrbk7svFyIdQQQEwgAHRYhBP2bIN08mBI+7q+MxRukFTjS5la1
+BQJZbhAyAAoJEBukFTjS5la10+gA/2wr/lG67+xA1n3+2tQkIf1254lnwr8NXhwg
+w4UAAbajAP9hOXzltmmHV4BaBm35GEv/A2iAABV6lzgvApmM9c445A==
+=i2Va
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3WrxMIKoZIzj0DAQcCAwS4HzEJ0YwXZ1SWciHOmWdfnESTvwC3Zb/sWRu8
+zdIeZzxAwu8lYQaDq/eOgKeXQVW5gxkQG5rCWUazbG+gCBEItBlDYXJvbCA8Y2Fy
+b2xAZXhhbXBsZS5uZXQ+iJAEExMIADgWIQRsYnNeRUzN15+mymAQeRE67BKC/QUC
+WW3WrwIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRAQeRE67BKC/czKAP4p
+26ygO/PtZluyOMFYj8cuFZ9Z9eygBH2Y3/mtn3gcOAD/VWpu9Rwz689TraDv/Sqg
+apYJ1rdJREHrbrcqKtuTqFiIdQQQEwgAHRYhBE0/WfTYAw/S2ESv66W6w+0SXMrl
+BQJZbhBhAAoJEKW6w+0SXMrlPYgA/21rYq9iItnLASDCdt4ZX6gPKEZVBFDk6850
+Gyvg3TrEAP9/9bjKEFCSbo6vFKONOEpKqA/9B85Ff+2jq1lvfafV4Q==
+=mwVS
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3WzRMIKoZIzj0DAQcCAwQrTeILyHVpkkDsAyAlY7wz0PYjG48ShCYeTX2z
+5f2bLxZGeepQeMiOXznPvCwRNMNpr63048+LGqu34Q9di5tvtBlEYXZpZCA8ZGF2
+aWRAZXhhbXBsZS5vcmc+iJAEExMIADgWIQSgYHY1GYyrosRn+qZM5btC45hAAAUC
+WW3WzQIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRBM5btC45hAAAm0AP4n
+GINm20BvnUWMHmgnUGSybMiuAvqi6itsstGNXKTuuQD/QmrIuGHUre+fitgNu4q2
+9ABx9BsKd3PAX1e4ZD/uBtKIdQQQEwgAHRYhBE0/WfTYAw/S2ESv66W6w+0SXMrl
+BQJZbhB0AAoJEKW6w+0SXMrlARwA/RiqKRh4rYtW5gP20PoQNYfS1qh+lDRTlhfp
+SSF5aKKFAP90s5/fp6n382IjbOhmQiEB9N4gv4pZT3YP13NQwAABbg==
+=bLxR
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3W3RMIKoZIzj0DAQcCAwQs0QS2PEUXhpmsPlaTFOsXd8AoYqpa6xcc0+AE
+Mck1EzlqRlxeibvYeh/+yxjl18Ouww/BERB+PcoABXp00zXztBlGcmFuayA8ZnJh
+bmtAZXhhbXBsZS5jb20+iJAEExMIADgWIQTOGg4Hz4ogy/jcR9bbkBfbrmzQ7wUC
+WW3W3QIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRDbkBfbrmzQ76cNAP9G
+mUKYA9CAx6OGzb9iY6pat6TJ3ghY2P3PIjafbbxZdgEAnX9Z/W8G+I4SrOzu34LS
+IETHEldWI+UbSc1n1qiJfUaIdQQQEwgAHRYhBE0/WfTYAw/S2ESv66W6w+0SXMrl
+BQJZbhCEAAoJEKW6w+0SXMrlepAA/3+AAaRQVfsU+zQtGg43VxAcfW+ezuUVCYUY
+IW2Lv+GkAP0WF7Nh5N4nDo/gC3WBW2zdWArlRaWa5NxcCquEUaE7Tg==
+=SWmz
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3W8RMIKoZIzj0DAQcCAwRTGb7wRrdPa+mXxUNJoYgWbKfMDQH9M1H366PQ
+ga8L32TYccFzyCD8DuRYOQxzhnCtSHtdzK4QAwwGLaJV6GRjtBlHcmFjZSA8Z3Jh
+Y2VAZXhhbXBsZS5uZXQ+iJAEExMIADgWIQS5NfS42gCa+8zdQThmU6GDAH+DRQUC
+WW3W8QIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRBmU6GDAH+DRbYAAP4q
+ZbYNAAtZOexWcv9Ap0nUnwOxpHWX7LaHsVRi4W21CwEAtliza9TA5UGcBjKpseiC
+qBs9LEpFd4DE2qh6nHpyy/6IdQQQEwgAHRYhBGxic15FTM3Xn6bKYBB5ETrsEoL9
+BQJZbhCyAAoJEBB5ETrsEoL9pVoBAPGc50vXiWmSAx8U573pqAyBsVPPMUlfrrgc
+tVZZQ9DyAP9LCpG1kJOnB1Fia1M6M/37FAwVjUerWTrp6XoG1888PYh1BBATCAAd
+FiEEoGB2NRmMq6LEZ/qmTOW7QuOYQAAFAlluEM4ACgkQTOW7QuOYQAB3HgD+Kw+R
+WbH8RcSlNbwlGWCWYwKvik7ukIMcTXXYD5azTYoBANF5Ym2n5RExmEd8nTrWu9MR
+TUlOgAXfzm/iH4+TNj2yiHUEEBMIAB0WIQTOGg4Hz4ogy/jcR9bbkBfbrmzQ7wUC
+WW4Q7AAKCRDbkBfbrmzQ7weXAP9OyFxzdpbq1R+V6T5WEckR5OtE6Va/7CHRPRW+
+kMNVjwD/YQZVbOCRxKybVbvPuF+29w7sWp4iAmmrmCFnKfgxZsQ=
+=r9Ly
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/trust-pgp/scenario2.asc b/tests/openpgp/trust-pgp/scenario2.asc
new file mode 100644
index 0000000..3a98621
--- /dev/null
+++ b/tests/openpgp/trust-pgp/scenario2.asc
@@ -0,0 +1,70 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW2+WxMIKoZIzj0DAQcCAwQnUnqiwvOPU7gGepFTew8Fk5kmVexr+PvaqXgv
+9wKxNzZrs4GvamULk9pl2euwJGKPBRJRz8RSNpW6HIIzAPoOtBlBbGljZSA8YWxp
+Y2VAZXhhbXBsZS5vcmc+iJAEExMIADgWIQT9myDdPJgSPu6vjMUbpBU40uZWtQUC
+WW2+WwIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRAbpBU40uZWtTs8AQC8
+6p4hEyInw17S3P4rVpHP+en+6YJDE7x12b2aevgzsQD/XPhh0PTrAlenhFdQjQbZ
+A4dNj5BcxKEIWunJICtZCo0=
+=rf4w
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3WihMIKoZIzj0DAQcCAwTtUYI84wfNPCwa/r2ke7tXz0uv/En9LQZbW0QE
+nzHigEvMXLfyjfjCf5tQ2eVbKLbABxtKwDtC2bv8dMcmgqd/tBlCb2JieSA8Ym9i
+YnlAZXhhbXBsZS5jb20+iJAEExMIADgWIQRNP1n02AMP0thEr+ulusPtElzK5QUC
+WW3WigIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRClusPtElzK5ZSOAQD1
+St647GAPOFIIYBDka3EGJeSan8i4f+u80jyplpWeggEA+z9VSDLd7JKMXqD3B/9T
+O+rBR22hpi+TILZrbk7svFyIeQQQEwgAIRYhBP2bIN08mBI+7q+MxRukFTjS5la1
+BQJZbjsoAwUBeAAKCRAbpBU40uZWtVGlAQCgHkwmJSATJbrqV7+h/1ByLDi4+thQ
+ApW8nRinGuwkxQD+NgjOVmkPGZtpvaBzLXJS/IdPAYBWAriAzDZEV2GchWM=
+=4Xcm
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3WrxMIKoZIzj0DAQcCAwS4HzEJ0YwXZ1SWciHOmWdfnESTvwC3Zb/sWRu8
+zdIeZzxAwu8lYQaDq/eOgKeXQVW5gxkQG5rCWUazbG+gCBEItBlDYXJvbCA8Y2Fy
+b2xAZXhhbXBsZS5uZXQ+iJAEExMIADgWIQRsYnNeRUzN15+mymAQeRE67BKC/QUC
+WW3WrwIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRAQeRE67BKC/czKAP4p
+26ygO/PtZluyOMFYj8cuFZ9Z9eygBH2Y3/mtn3gcOAD/VWpu9Rwz689TraDv/Sqg
+apYJ1rdJREHrbrcqKtuTqFiIdQQQEwgAHRYhBE0/WfTYAw/S2ESv66W6w+0SXMrl
+BQJZbjteAAoJEKW6w+0SXMrlkJQBAO19erLoHXOqUI01Wl0tcaKIwEB5HkIHLh0w
+cCTOG4bDAQCCG8a8D1mg9jVPukBzTBUZGpDZmg/U3JGW3XE6rKlKXQ==
+=Df0N
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3WzRMIKoZIzj0DAQcCAwQrTeILyHVpkkDsAyAlY7wz0PYjG48ShCYeTX2z
+5f2bLxZGeepQeMiOXznPvCwRNMNpr63048+LGqu34Q9di5tvtBlEYXZpZCA8ZGF2
+aWRAZXhhbXBsZS5vcmc+iJAEExMIADgWIQSgYHY1GYyrosRn+qZM5btC45hAAAUC
+WW3WzQIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRBM5btC45hAAAm0AP4n
+GINm20BvnUWMHmgnUGSybMiuAvqi6itsstGNXKTuuQD/QmrIuGHUre+fitgNu4q2
+9ABx9BsKd3PAX1e4ZD/uBtKIdQQQEwgAHRYhBP2bIN08mBI+7q+MxRukFTjS5la1
+BQJZbkUBAAoJEBukFTjS5la1zSgA/A6ei6bus+VtQtL1rsJfovwoxnyAq+QzCcJL
+ZheUUK3LAQCK+rVE1Yn9QsFoNYZUgLHrnQDtSVq9ClJvNw/Wuz7DpQ==
+=No85
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3W3RMIKoZIzj0DAQcCAwQs0QS2PEUXhpmsPlaTFOsXd8AoYqpa6xcc0+AE
+Mck1EzlqRlxeibvYeh/+yxjl18Ouww/BERB+PcoABXp00zXztBlGcmFuayA8ZnJh
+bmtAZXhhbXBsZS5jb20+iJAEExMIADgWIQTOGg4Hz4ogy/jcR9bbkBfbrmzQ7wUC
+WW3W3QIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRDbkBfbrmzQ76cNAP9G
+mUKYA9CAx6OGzb9iY6pat6TJ3ghY2P3PIjafbbxZdgEAnX9Z/W8G+I4SrOzu34LS
+IETHEldWI+UbSc1n1qiJfUaIeQQQEwgAIRYhBKBgdjUZjKuixGf6pkzlu0LjmEAA
+BQJZbkUwAwUBeAAKCRBM5btC45hAAJF0AQD3lBQszLXrlSnCLuHfQxbS/p05DURZ
+HRi8MbTqkrcgrQD8Cs3gwQCBkPUrx8boAyjcuX1BK/TYZ1Gg8hWkozNr1lI=
+=HwV/
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3W8RMIKoZIzj0DAQcCAwRTGb7wRrdPa+mXxUNJoYgWbKfMDQH9M1H366PQ
+ga8L32TYccFzyCD8DuRYOQxzhnCtSHtdzK4QAwwGLaJV6GRjtBlHcmFjZSA8Z3Jh
+Y2VAZXhhbXBsZS5uZXQ+iJAEExMIADgWIQS5NfS42gCa+8zdQThmU6GDAH+DRQUC
+WW3W8QIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRBmU6GDAH+DRbYAAP4q
+ZbYNAAtZOexWcv9Ap0nUnwOxpHWX7LaHsVRi4W21CwEAtliza9TA5UGcBjKpseiC
+qBs9LEpFd4DE2qh6nHpyy/6IdQQQEwgAHRYhBM4aDgfPiiDL+NxH1tuQF9uubNDv
+BQJZbkVQAAoJENuQF9uubNDvyrkBAICiFq2dTFzLrXNsItwpPrB20trzEPM/JAxa
+lzSyknJMAQDBCj8nyEtlpkYh9t9ovy/x75D1OUBFFYHOQXCMy0QyRA==
+=yoqI
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/trust-pgp/scenario3.asc b/tests/openpgp/trust-pgp/scenario3.asc
new file mode 100644
index 0000000..240afd5
--- /dev/null
+++ b/tests/openpgp/trust-pgp/scenario3.asc
@@ -0,0 +1,58 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW2+WxMIKoZIzj0DAQcCAwQnUnqiwvOPU7gGepFTew8Fk5kmVexr+PvaqXgv
+9wKxNzZrs4GvamULk9pl2euwJGKPBRJRz8RSNpW6HIIzAPoOtBlBbGljZSA8YWxp
+Y2VAZXhhbXBsZS5vcmc+iJAEExMIADgWIQT9myDdPJgSPu6vjMUbpBU40uZWtQUC
+WW2+WwIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRAbpBU40uZWtTs8AQC8
+6p4hEyInw17S3P4rVpHP+en+6YJDE7x12b2aevgzsQD/XPhh0PTrAlenhFdQjQbZ
+A4dNj5BcxKEIWunJICtZCo0=
+=rf4w
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3WihMIKoZIzj0DAQcCAwTtUYI84wfNPCwa/r2ke7tXz0uv/En9LQZbW0QE
+nzHigEvMXLfyjfjCf5tQ2eVbKLbABxtKwDtC2bv8dMcmgqd/tBlCb2JieSA8Ym9i
+YnlAZXhhbXBsZS5jb20+iJAEExMIADgWIQRNP1n02AMP0thEr+ulusPtElzK5QUC
+WW3WigIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRClusPtElzK5ZSOAQD1
+St647GAPOFIIYBDka3EGJeSan8i4f+u80jyplpWeggEA+z9VSDLd7JKMXqD3B/9T
+O+rBR22hpi+TILZrbk7svFyIeQQQEwgAIRYhBP2bIN08mBI+7q+MxRukFTjS5la1
+BQJZbmYmAwUCeAAKCRAbpBU40uZWtSQhAQD2HLi7PUipgcO9N+KEJLKl2T9ralzj
+O1PMy8IbxnG86AD/Ya541TcH9oxZUWm5dsHd/eoBnSu2WwWkLPNHirRkzwE=
+=R1uZ
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3WrxMIKoZIzj0DAQcCAwS4HzEJ0YwXZ1SWciHOmWdfnESTvwC3Zb/sWRu8
+zdIeZzxAwu8lYQaDq/eOgKeXQVW5gxkQG5rCWUazbG+gCBEItBlDYXJvbCA8Y2Fy
+b2xAZXhhbXBsZS5uZXQ+iJAEExMIADgWIQRsYnNeRUzN15+mymAQeRE67BKC/QUC
+WW3WrwIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRAQeRE67BKC/czKAP4p
+26ygO/PtZluyOMFYj8cuFZ9Z9eygBH2Y3/mtn3gcOAD/VWpu9Rwz689TraDv/Sqg
+apYJ1rdJREHrbrcqKtuTqFiIeQQQEwgAIRYhBE0/WfTYAw/S2ESv66W6w+0SXMrl
+BQJZbmZIAwUCeAAKCRClusPtElzK5YuLAP0b5nCuz6p6DDrHB0rtwfhEfJQgvsEc
+zGE2Hh5P5fXP/AEA2Gt8LEWiHYNGWu6ZN02oyCoNUEfZZFva59IIPrzPDHU=
+=S6Nc
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3WzRMIKoZIzj0DAQcCAwQrTeILyHVpkkDsAyAlY7wz0PYjG48ShCYeTX2z
+5f2bLxZGeepQeMiOXznPvCwRNMNpr63048+LGqu34Q9di5tvtBlEYXZpZCA8ZGF2
+aWRAZXhhbXBsZS5vcmc+iJAEExMIADgWIQSgYHY1GYyrosRn+qZM5btC45hAAAUC
+WW3WzQIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRBM5btC45hAAAm0AP4n
+GINm20BvnUWMHmgnUGSybMiuAvqi6itsstGNXKTuuQD/QmrIuGHUre+fitgNu4q2
+9ABx9BsKd3PAX1e4ZD/uBtKIeQQQEwgAIRYhBGxic15FTM3Xn6bKYBB5ETrsEoL9
+BQJZbmZ0AwUCeAAKCRAQeRE67BKC/eFYAQDaKoyQZYnNH/62hydWITZ1nOYM/h6i
+6L/b+XqB9DD0ewD9FAbO1wzassj6FmZMZDaraqdljTX+94JY5E3GJ8EQXo4=
+=kaec
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3W3RMIKoZIzj0DAQcCAwQs0QS2PEUXhpmsPlaTFOsXd8AoYqpa6xcc0+AE
+Mck1EzlqRlxeibvYeh/+yxjl18Ouww/BERB+PcoABXp00zXztBlGcmFuayA8ZnJh
+bmtAZXhhbXBsZS5jb20+iJAEExMIADgWIQTOGg4Hz4ogy/jcR9bbkBfbrmzQ7wUC
+WW3W3QIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRDbkBfbrmzQ76cNAP9G
+mUKYA9CAx6OGzb9iY6pat6TJ3ghY2P3PIjafbbxZdgEAnX9Z/W8G+I4SrOzu34LS
+IETHEldWI+UbSc1n1qiJfUaIeQQQEwgAIRYhBKBgdjUZjKuixGf6pkzlu0LjmEAA
+BQJZbmaiAwUCeAAKCRBM5btC45hAAMcRAP9dcKO3ETB52AsFdBp2iJVjqJ5JiftN
+B/2FZBxPtSjXpAD/YdDzs+zNaAUlFIFmXzP9EmIqmXhC6XSiASrNd5EW33A=
+=DXNa
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/trust-pgp/scenario4.asc b/tests/openpgp/trust-pgp/scenario4.asc
new file mode 100644
index 0000000..7860c95
--- /dev/null
+++ b/tests/openpgp/trust-pgp/scenario4.asc
@@ -0,0 +1,84 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW2+WxMIKoZIzj0DAQcCAwQnUnqiwvOPU7gGepFTew8Fk5kmVexr+PvaqXgv
+9wKxNzZrs4GvamULk9pl2euwJGKPBRJRz8RSNpW6HIIzAPoOtBlBbGljZSA8YWxp
+Y2VAZXhhbXBsZS5vcmc+iJAEExMIADgWIQT9myDdPJgSPu6vjMUbpBU40uZWtQUC
+WW2+WwIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRAbpBU40uZWtTs8AQC8
+6p4hEyInw17S3P4rVpHP+en+6YJDE7x12b2aevgzsQD/XPhh0PTrAlenhFdQjQbZ
+A4dNj5BcxKEIWunJICtZCo0=
+=rf4w
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3WihMIKoZIzj0DAQcCAwTtUYI84wfNPCwa/r2ke7tXz0uv/En9LQZbW0QE
+nzHigEvMXLfyjfjCf5tQ2eVbKLbABxtKwDtC2bv8dMcmgqd/tBlCb2JieSA8Ym9i
+YnlAZXhhbXBsZS5jb20+iJAEExMIADgWIQRNP1n02AMP0thEr+ulusPtElzK5QUC
+WW3WigIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRClusPtElzK5ZSOAQD1
+St647GAPOFIIYBDka3EGJeSan8i4f+u80jyplpWeggEA+z9VSDLd7JKMXqD3B/9T
+O+rBR22hpi+TILZrbk7svFyIlAQQEwgAPBYhBP2bIN08mBI+7q+MxRukFTjS5la1
+BQJZbm5IAwUCeBqGPFtePl0rW0AuXWV4YW1wbGVcLmNvbT4kAAAKCRAbpBU40uZW
+tb+2APsFKgWxiLtSbpcekarOlPrw014LVinLGah3VE1Izay+tAEA+0INHdcNoz64
+kRE/2siUnx1ksrWcWvJbvNMteknXhzY=
+=UQni
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3WrxMIKoZIzj0DAQcCAwS4HzEJ0YwXZ1SWciHOmWdfnESTvwC3Zb/sWRu8
+zdIeZzxAwu8lYQaDq/eOgKeXQVW5gxkQG5rCWUazbG+gCBEItBlDYXJvbCA8Y2Fy
+b2xAZXhhbXBsZS5uZXQ+iJAEExMIADgWIQRsYnNeRUzN15+mymAQeRE67BKC/QUC
+WW3WrwIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRAQeRE67BKC/czKAP4p
+26ygO/PtZluyOMFYj8cuFZ9Z9eygBH2Y3/mtn3gcOAD/VWpu9Rwz689TraDv/Sqg
+apYJ1rdJREHrbrcqKtuTqFiIdQQQEwgAHRYhBE0/WfTYAw/S2ESv66W6w+0SXMrl
+BQJZbm6PAAoJEKW6w+0SXMrlWj8A/2UdgyhbV+tLjyFb87iBiaWxSIVfiVyjhLZN
+htPTrKb2AP4yIRxJ3x0LmRSDLkZ/QIQmgahlAXRmKCXSRAB8x2KRsQ==
+=Zbpr
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3WzRMIKoZIzj0DAQcCAwQrTeILyHVpkkDsAyAlY7wz0PYjG48ShCYeTX2z
+5f2bLxZGeepQeMiOXznPvCwRNMNpr63048+LGqu34Q9di5tvtBlEYXZpZCA8ZGF2
+aWRAZXhhbXBsZS5vcmc+iJAEExMIADgWIQSgYHY1GYyrosRn+qZM5btC45hAAAUC
+WW3WzQIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRBM5btC45hAAAm0AP4n
+GINm20BvnUWMHmgnUGSybMiuAvqi6itsstGNXKTuuQD/QmrIuGHUre+fitgNu4q2
+9ABx9BsKd3PAX1e4ZD/uBtKIlAQQEwgAPBYhBP2bIN08mBI+7q+MxRukFTjS5la1
+BQJZbm5uAwUCeBqGPFtePl0rW0AuXWV4YW1wbGVcLm9yZz4kAAAKCRAbpBU40uZW
+tYGkAQDcxaTENxUFCcwyuv/pOpNr51Q7bhCcWVPd3Zn1t3yurQD+KDre0hsrR0Rf
+kiq5JYhqh8sEejmFQ1EtcCNI2x8CvHg=
+=W5g4
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3W3RMIKoZIzj0DAQcCAwQs0QS2PEUXhpmsPlaTFOsXd8AoYqpa6xcc0+AE
+Mck1EzlqRlxeibvYeh/+yxjl18Ouww/BERB+PcoABXp00zXztBlGcmFuayA8ZnJh
+bmtAZXhhbXBsZS5jb20+iJAEExMIADgWIQTOGg4Hz4ogy/jcR9bbkBfbrmzQ7wUC
+WW3W3QIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRDbkBfbrmzQ76cNAP9G
+mUKYA9CAx6OGzb9iY6pat6TJ3ghY2P3PIjafbbxZdgEAnX9Z/W8G+I4SrOzu34LS
+IETHEldWI+UbSc1n1qiJfUaIdQQQEwgAHRYhBKBgdjUZjKuixGf6pkzlu0LjmEAA
+BQJZbm7vAAoJEEzlu0LjmEAAmT0A/3kZ3vms9aDuS2OD9yE/KoluBQi1UWR59V/2
+JHomhTiRAP9GI/01N3pRty986m4dVBbrXpT39ZkEj4q+zkn1uNeQHA==
+=UqlD
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3W8RMIKoZIzj0DAQcCAwRTGb7wRrdPa+mXxUNJoYgWbKfMDQH9M1H366PQ
+ga8L32TYccFzyCD8DuRYOQxzhnCtSHtdzK4QAwwGLaJV6GRjtBlHcmFjZSA8Z3Jh
+Y2VAZXhhbXBsZS5uZXQ+iJAEExMIADgWIQS5NfS42gCa+8zdQThmU6GDAH+DRQUC
+WW3W8QIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRBmU6GDAH+DRbYAAP4q
+ZbYNAAtZOexWcv9Ap0nUnwOxpHWX7LaHsVRi4W21CwEAtliza9TA5UGcBjKpseiC
+qBs9LEpFd4DE2qh6nHpyy/6IdQQQEwgAHRYhBAOJwLeZDhBSCzNPI3VvFXHtqRhL
+BQJZbm85AAoJEHVvFXHtqRhL6N0BAPjsViTQhc/t9zbC7Jf3bRLQTYjwR5EtW4Wu
+IZZeByYXAQDw0Wofsq945J5oRLoTPdc264dBv8ojBr0/1uFWOvci/w==
+=q1yC
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mFIEWW3XBxMIKoZIzj0DAQcCAwSINFpTZUYnxDDj3k16ljZIt58rh3cuUNIvUcqR
+zR9kdlmudQTaf1zUsW6F3r+t91t88kaA2Fcci3wkU0CAob0WtBlIZWlkaSA8aGVp
+ZGlAZXhhbXBsZS5vcmc+iJAEExMIADgWIQQDicC3mQ4QUgszTyN1bxVx7akYSwUC
+WW3XBwIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRB1bxVx7akYS3BcAP9J
+XIhGIadg+SoFWoZ8jYyVOA3z66Ku6vYl2Rw+jKUIQwD+Pc54tFFPV2hycSe9JPWy
+uaVfFlNs1RyWcCVrY5l3swSIeQQQEwgAIRYhBKBgdjUZjKuixGf6pkzlu0LjmEAA
+BQJZbm8aAwUCeAAKCRBM5btC45hAAPABAPwLtRtV1gnk6qbyb9DvvHbG1kd2sqQ5
+mBM7cw6rPmf2EgEA3V3J9D7/4hbF/tulACVEpW9yvZq3wnEj0GSMpF6qQDE=
+=7uOj
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/use-exact-key.scm b/tests/openpgp/use-exact-key.scm
new file mode 100755
index 0000000..8bff9af
--- /dev/null
+++ b/tests/openpgp/use-exact-key.scm
@@ -0,0 +1,69 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+;; Import the sample key
+;;
+;; pub 1024R/8BC90111 2015-12-02
+;; Key fingerprint = E657 FB60 7BB4 F21C 90BB 6651 BC06 7AF2 8BC9 0111
+;; uid [ultimate] Barrett Brown <barrett@example.org>
+;; sub 1024R/3E880CFF 2015-12-02 (encryption)
+;; sub 1024R/F5F77B83 2015-12-02 (signing)
+;; sub 1024R/45117079 2015-12-02 (encryption)
+;; sub 1024R/1EA97479 2015-12-02 (signing)
+
+(info "Importing public key.")
+(call-check
+ `(,(tool 'gpg) --import
+ ,(in-srcdir "tests" "openpgp" "samplekeys/E657FB607BB4F21C90BB6651BC067AF28BC90111.asc")))
+
+;; By default, the most recent, valid signing subkey (1EA97479).
+(for-each-p
+ "Checking that the most recent, valid signing subkey is used by default"
+ (lambda (keyid)
+ (tr:do
+ (tr:pipe-do
+ (pipe:defer (lambda (sink) (display "" (fdopen sink "w"))))
+ (pipe:gpg `(-s -u ,keyid))
+ (pipe:gpg '(--verify --status-fd=1)))
+ (tr:call-with-content
+ (lambda (c)
+ (unless (string-contains?
+ c "VALIDSIG 5FBA84ACE02DCB17DA3DFF6BBCA43C441EA97479")
+ (exit 1))))))
+ '("8BC90111" "3E880CFF" "F5F77B83" "45117079" "1EA97479"))
+
+;; But, if we request a particular signing key, we should get it.
+(for-each-p
+ "Checking that we can select a specific signing key"
+ (lambda (keyid)
+ (tr:do
+ (tr:pipe-do
+ (pipe:defer (lambda (sink) (display "" (fdopen sink "w"))))
+ (pipe:gpg `(-s -u ,(string-append keyid "!")))
+ (pipe:gpg '(--verify --status-fd=1)))
+ (tr:call-with-content
+ (lambda (c)
+ ;; XXX we do not have a regexp library
+ (unless (and (string-contains? c "VALIDSIG")
+ (string-contains? c keyid))
+ (exit 1))))))
+ '("8BC90111" "F5F77B83" "1EA97479"))
diff --git a/tests/openpgp/verify-multifile.scm b/tests/openpgp/verify-multifile.scm
new file mode 100755
index 0000000..9ebb672
--- /dev/null
+++ b/tests/openpgp/verify-multifile.scm
@@ -0,0 +1,41 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-legacy-environment)
+
+(define files '("clearsig-1-key-1.asc" "signed-1-key-1.asc"))
+
+(info "Checking verification of supplied files using --multifile.")
+
+(let* ((status
+ (call-popen
+ `(,@gpg --verify --multifile --status-fd=1
+ ,@(map (lambda (name) (in-srcdir "tests" "openpgp" "samplemsgs" name)) files))
+ ""))
+ (lines (map (lambda (l)
+ (assert (string-prefix? l "[GNUPG:] "))
+ ;; Split, and strip the prefix.
+ (cdr (string-split l #\space)))
+ (string-split-newlines status))))
+ (assert
+ (= 2 (length (filter (lambda (l)
+ (and (equal? (car l) "GOODSIG")
+ (equal? (caddr l) "steve.biko@example.net")))
+ lines)))))
diff --git a/tests/openpgp/verify.scm b/tests/openpgp/verify.scm
new file mode 100755
index 0000000..b4dd49b
--- /dev/null
+++ b/tests/openpgp/verify.scm
@@ -0,0 +1,87 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(load (in-srcdir "tests" "openpgp" "signed-messages.scm"))
+(setup-legacy-environment)
+
+;;
+;; Two simple tests to check that verify fails for bad input data
+;;
+(for-each-p
+ "Checking bogus signature"
+ (lambda (char)
+ (lettmp (x)
+ (call-with-binary-output-file
+ x
+ (lambda (port)
+ (display (make-string 64 (integer->char (string->number char)))
+ port)))
+ (if (= 0 (call `(,@GPG --verify ,x data-500)))
+ (fail "no error code from verify"))))
+ '("#x2d" "#xca"))
+
+;; Fixme: We need more tests with manipulated cleartext signatures.
+
+;;
+;; Now run the tests.
+;;
+(for-each-p
+ "Checking that a valid signature is verified as such"
+ (lambda (armored-file)
+ (pipe:do
+ (pipe:echo (eval armored-file (current-environment)))
+ (pipe:spawn `(,@GPG --verify))))
+ '(msg_ols_asc msg_cols_asc msg_sl_asc msg_oolss_asc msg_cls_asc msg_clss_asc))
+
+(for-each-p
+ "Checking that a valid signature over multiple messages is verified as such"
+ (lambda (armored-file)
+ (pipe:do
+ (pipe:echo (eval armored-file (current-environment)))
+ (pipe:spawn `(,@GPG --verify --allow-multiple-messages)))
+ (catch '()
+ (pipe:do
+ (pipe:defer (lambda (sink)
+ (display armored-file (fdopen sink "w"))))
+ (pipe:spawn `(,@GPG --verify)))
+ (fail "verification succeeded but should not")))
+ '(msg_olsols_asc_multiple msg_clsclss_asc_multiple))
+
+(for-each-p
+ "Checking that an invalid signature is verified as such"
+ (lambda (armored-file)
+ (catch '()
+ (pipe:do
+ (pipe:echo (eval armored-file (current-environment)))
+ (pipe:spawn `(,@GPG --verify)))
+ (fail "verification succeeded but should not")))
+ '(bad_ls_asc bad_fols_asc bad_olsf_asc bad_ools_asc))
+
+
+;;; Need to import the ed25519 sample key used for
+;;; the next two tests.
+(call-check `(,@GPG --quiet --yes --import ,(in-srcdir "tests" "openpgp" key-file2)))
+(for-each-p
+ "Checking that a valid Ed25519 signature is verified as such"
+ (lambda (armored-file)
+ (pipe:do
+ (pipe:echo (eval armored-file (current-environment)))
+ (pipe:spawn `(,@GPG --verify))))
+ '(msg_ed25519_rshort msg_ed25519_sshort))
diff --git a/tests/openpgp/version.scm b/tests/openpgp/version.scm
new file mode 100755
index 0000000..c2252c5
--- /dev/null
+++ b/tests/openpgp/version.scm
@@ -0,0 +1,25 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2016 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(load (in-srcdir "tests" "openpgp" "defs.scm"))
+(setup-environment)
+
+(info "Printing the GPG version")
+(assert (string-contains? (call-check `(,@GPG --version))
+ "gpg (GnuPG) 2."))
diff --git a/tests/pkits/ChangeLog-2011 b/tests/pkits/ChangeLog-2011
new file mode 100644
index 0000000..d66e474
--- /dev/null
+++ b/tests/pkits/ChangeLog-2011
@@ -0,0 +1,75 @@
+2011-12-01 Werner Koch <wk@g10code.com>
+
+ NB: ChangeLog files are no longer manually maintained. Starting
+ on December 1st, 2011 we put change information only in the GIT
+ commit log, and generate a top-level ChangeLog file from logs at
+ "make dist". See doc/HACKING for details.
+
+2009-03-03 Werner Koch <wk@g10code.com>
+
+ * inittests (clean_files): Use /bin/pwd here as well.
+
+ * Makefile.am (run-all-tests): Also use /bin/pwd here.
+
+2009-02-19 Werner Koch <wk@g10code.com>
+
+ * Makefile.am (TESTS_ENVIRONMENT): Use /bin/pwd
+ * common.sh: Ditto.
+
+2008-02-19 Werner Koch <wk@g10code.com>
+
+ * inittests: Unpack test data onlyu if available.
+ * common.sh: Skip tests if PKITS test data is not available.
+ * Makefile.am: Do not distribute test data. This allows to
+ include the test suite in the distribution.
+
+ * signature-verification: New.
+ * validity-periods: New.
+ * verifying-name-chaining: New.
+ * basic-certificate-revocation: New.
+ * verifying-paths-self-issued: New.
+ * verifying-basic-constraints: New.
+ * key-usage: New.
+ * certificate-policies: New.
+ * require-explicit-policy: New.
+ * policy-mappings: New.
+ * inhibit-policy-mapping: New.
+ * inhibit-any-policy: New.
+ * name-constraints: New.
+ * distribution-points: New.
+ * delta-crls: New.
+ * private-certificate-extensions: New.
+ * Makefile.am (testscripts): Add them.
+
+ * import-all-certs.data: Add section numbers.
+
+2008-02-18 Werner Koch <wk@g10code.com>
+
+ * import-all-certs.data: Adjust import tests results. Almost all
+ certificates should now be importable due to relaxed basic checks.
+
+ * inittests (clean_files): Disable all dirmngr access.
+
+2006-05-02 Werner Koch <wk@g10code.com>
+
+ * PKITS_data.tar.bz2: Repackaged new copy because the old one got
+ corrupted by the conversion from CVS to SVN.
+
+2004-08-16 Werner Koch <wk@g10code.de>
+
+ Started implementing PKITS based tests.
+
+
+ Copyright 2004, 2008 Free Software Foundation, Inc.
+
+ This file is free software; as a special exception the author gives
+ unlimited permission to copy and/or distribute it, with or without
+ modifications, as long as this notice is preserved.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+Local Variables:
+buffer-read-only: t
+End:
diff --git a/tests/pkits/Makefile.am b/tests/pkits/Makefile.am
new file mode 100644
index 0000000..3dc2f16
--- /dev/null
+++ b/tests/pkits/Makefile.am
@@ -0,0 +1,75 @@
+# Makefile.am - tests using NIST's PKITS
+# Copyright (C) 2004, 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+
+## Process this file with automake to produce Makefile.in
+
+GPGSM = ../../sm/gpgsm
+
+TESTS_ENVIRONMENT = GNUPGHOME=`/bin/pwd` GPG_AGENT_INFO= LC_ALL=C \
+ GPGSM=$(GPGSM) silent=yes
+
+
+testscripts = import-all-certs validate-all-certs \
+ signature-verification \
+ validity-periods \
+ verifying-name-chaining \
+ basic-certificate-revocation \
+ verifying-paths-self-issued \
+ verifying-basic-constraints \
+ key-usage \
+ certificate-policies \
+ require-explicit-policy \
+ policy-mappings \
+ inhibit-policy-mapping \
+ inhibit-any-policy \
+ name-constraints \
+ distribution-points \
+ delta-crls \
+ private-certificate-extensions
+
+
+EXTRA_DIST = inittests runtest common.sh $(testscripts) ChangeLog-2011 \
+ import-all-certs.data
+
+TESTS =
+
+CLEANFILES = inittests.stamp scratch.*.tmp x y z out err *.lock .\#lk* *.log
+
+DISTCLEANFILES = pubring.kbx~ random_seed
+
+all-local: inittests.stamp
+
+clean-local:
+ srcdir=$(srcdir) $(TESTS_ENVIRONMENT) $(srcdir)/inittests --clean
+
+inittests.stamp: inittests
+ srcdir=$(srcdir) $(TESTS_ENVIRONMENT) $(srcdir)/inittests
+ echo timestamp >./inittests.stamp
+
+
+run-all-tests: inittests.stamp
+ @set -e; \
+ GNUPGHOME=`/bin/pwd`; export GNUPGHOME;\
+ unset GPG_AGENT_INFO; \
+ for tst in $(testscripts); do \
+ if ./$${tst}; then : ; \
+ elif test $$? -eq 77; then echo "- SKIP $$tst"; \
+ fi; \
+ done
+
+
diff --git a/tests/pkits/Makefile.in b/tests/pkits/Makefile.in
new file mode 100644
index 0000000..accdff2
--- /dev/null
+++ b/tests/pkits/Makefile.in
@@ -0,0 +1,695 @@
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am - tests using NIST's PKITS
+# Copyright (C) 2004, 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+TESTS =
+subdir = tests/pkits
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/autobuild.m4 \
+ $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/ksba.m4 \
+ $(top_srcdir)/m4/lcmessage.m4 $(top_srcdir)/m4/ldap.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libassuan.m4 \
+ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/npth.m4 $(top_srcdir)/m4/ntbtls.m4 \
+ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \
+ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/readline.m4 \
+ $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \
+ $(top_srcdir)/m4/tar-ustar.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ fi; \
+}
+am__DIST_COMMON = $(srcdir)/Makefile.in \
+ $(top_srcdir)/build-aux/mkinstalldirs README
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+AWK_HEX_NUMBER_OPTION = @AWK_HEX_NUMBER_OPTION@
+BUILD_FILEVERSION = @BUILD_FILEVERSION@
+BUILD_HOSTNAME = @BUILD_HOSTNAME@
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+BUILD_REVISION = @BUILD_REVISION@
+BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
+BUILD_VERSION = @BUILD_VERSION@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DL_LIBS = @DL_LIBS@
+DNSLIBS = @DNSLIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENCFS = @ENCFS@
+EXEEXT = @EXEEXT@
+FUSERMOUNT = @FUSERMOUNT@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNUPG_AGENT_PGM = @GNUPG_AGENT_PGM@
+GNUPG_DIRMNGR_LDAP_PGM = @GNUPG_DIRMNGR_LDAP_PGM@
+GNUPG_DIRMNGR_PGM = @GNUPG_DIRMNGR_PGM@
+GNUPG_PINENTRY_PGM = @GNUPG_PINENTRY_PGM@
+GNUPG_PROTECT_TOOL_PGM = @GNUPG_PROTECT_TOOL_PGM@
+GNUPG_SCDAEMON_PGM = @GNUPG_SCDAEMON_PGM@
+GPGKEYS_LDAP = @GPGKEYS_LDAP@
+GPGRT_CONFIG = @GPGRT_CONFIG@
+GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
+GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
+GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
+GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
+GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+KSBA_CFLAGS = @KSBA_CFLAGS@
+KSBA_CONFIG = @KSBA_CONFIG@
+KSBA_LIBS = @KSBA_LIBS@
+LBER_LIBS = @LBER_LIBS@
+LDAPLIBS = @LDAPLIBS@
+LDAP_CPPFLAGS = @LDAP_CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
+LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
+LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@
+LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBOBJS = @LIBOBJS@
+LIBREADLINE = @LIBREADLINE@
+LIBS = @LIBS@
+LIBUSB_CPPFLAGS = @LIBUSB_CPPFLAGS@
+LIBUSB_LIBS = @LIBUSB_LIBS@
+LIBUTIL_LIBS = @LIBUTIL_LIBS@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NETLIBS = @NETLIBS@
+NPTH_CFLAGS = @NPTH_CFLAGS@
+NPTH_CONFIG = @NPTH_CONFIG@
+NPTH_LIBS = @NPTH_LIBS@
+NTBTLS_CFLAGS = @NTBTLS_CFLAGS@
+NTBTLS_CONFIG = @NTBTLS_CONFIG@
+NTBTLS_LIBS = @NTBTLS_LIBS@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_GT = @PACKAGE_GT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SENDMAIL = @SENDMAIL@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHRED = @SHRED@
+SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
+SQLITE3_LIBS = @SQLITE3_LIBS@
+STRIP = @STRIP@
+SYSROOT = @SYSROOT@
+SYS_SOCKET_H = @SYS_SOCKET_H@
+TAR = @TAR@
+USE_C99_CFLAGS = @USE_C99_CFLAGS@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+W32SOCKLIBS = @W32SOCKLIBS@
+WINDRES = @WINDRES@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+YAT2M = @YAT2M@
+ZLIBS = @ZLIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+GPGSM = ../../sm/gpgsm
+TESTS_ENVIRONMENT = GNUPGHOME=`/bin/pwd` GPG_AGENT_INFO= LC_ALL=C \
+ GPGSM=$(GPGSM) silent=yes
+
+testscripts = import-all-certs validate-all-certs \
+ signature-verification \
+ validity-periods \
+ verifying-name-chaining \
+ basic-certificate-revocation \
+ verifying-paths-self-issued \
+ verifying-basic-constraints \
+ key-usage \
+ certificate-policies \
+ require-explicit-policy \
+ policy-mappings \
+ inhibit-policy-mapping \
+ inhibit-any-policy \
+ name-constraints \
+ distribution-points \
+ delta-crls \
+ private-certificate-extensions
+
+EXTRA_DIST = inittests runtest common.sh $(testscripts) ChangeLog-2011 \
+ import-all-certs.data
+
+CLEANFILES = inittests.stamp scratch.*.tmp x y z out err *.lock .\#lk* *.log
+DISTCLEANFILES = pubring.kbx~ random_seed
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/pkits/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu tests/pkits/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ $(am__tty_colors); \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=XPASS; \
+ ;; \
+ *) \
+ col=$$grn; res=PASS; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xfail=`expr $$xfail + 1`; \
+ col=$$lgn; res=XFAIL; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=FAIL; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ col=$$blu; res=SKIP; \
+ fi; \
+ echo "$${col}$$res$${std}: $$tst"; \
+ done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="$$All$$all $$tests passed"; \
+ else \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all $$tests failed"; \
+ else \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ if test "$$failed" -eq 0; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ fi; \
+ echo "$${col}$$dashes$${std}"; \
+ echo "$${col}$$banner$${std}"; \
+ test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
+ test -z "$$report" || echo "$${col}$$report$${std}"; \
+ echo "$${col}$$dashes$${std}"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile all-local
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-local mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: all all-am all-local check check-TESTS check-am clean \
+ clean-generic clean-local cscopelist-am ctags-am distclean \
+ distclean-generic distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic pdf pdf-am ps ps-am tags-am uninstall \
+ uninstall-am
+
+.PRECIOUS: Makefile
+
+
+all-local: inittests.stamp
+
+clean-local:
+ srcdir=$(srcdir) $(TESTS_ENVIRONMENT) $(srcdir)/inittests --clean
+
+inittests.stamp: inittests
+ srcdir=$(srcdir) $(TESTS_ENVIRONMENT) $(srcdir)/inittests
+ echo timestamp >./inittests.stamp
+
+run-all-tests: inittests.stamp
+ @set -e; \
+ GNUPGHOME=`/bin/pwd`; export GNUPGHOME;\
+ unset GPG_AGENT_INFO; \
+ for tst in $(testscripts); do \
+ if ./$${tst}; then : ; \
+ elif test $$? -eq 77; then echo "- SKIP $$tst"; \
+ fi; \
+ done
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tests/pkits/README b/tests/pkits/README
new file mode 100644
index 0000000..06aa97b
--- /dev/null
+++ b/tests/pkits/README
@@ -0,0 +1,37 @@
+tests/pkits/README
+
+These are tests based on NIST's Public Key Interoperability Test Suite
+(PKITS) as downloaded on 2006-05-02 from
+http://csrc.nist.gov/pki/testing/x509paths.html .
+
+README - this file.
+PKITS_data.tar.bz2 - the original ZIP file, repackaged as a tarball.
+Makefile.am - Part of our build system.
+import-all-certs - Run a simple import test on all certificates
+validate-all-certs - Run an import and validate test on all certificates
+signature-verification - PKITS test 4.1
+validity-periods - PKITS test 4.2
+verifying-name-chaining - PKITS test 4.3
+basic-certificate-revocation - PKITS test 4.4
+verifying-paths-self-issued - PKITS test 4.5
+verifying-basic-constraints - PKITS test 4.6
+key-usage - PKITS test 4.7
+certificate-policies - PKITS test 4.8
+require-explicit-policy - PKITS test 4.9
+policy-mappings - PKITS test 4.10
+inhibit-policy-mapping - PKITS test 4.11
+inhibit-any-policy - PKITS test 4.12
+name-constraints - PKITS test 4.13
+distribution-points - PKITS test 4.14
+delta-crls - PKITS test 4.15
+private-certificate-extensions - PKITS test 4.16
+
+
+The password for the p12 files is "password".
+
+You may run the tests as usual with "make check" or after a plain make
+in this directory you may run the tests individually. When run in
+this way they will print easy to parse output to stdout. To run all
+tests in this mode, use "make run-all-tests". All test scripts create
+a log file with the suffix ".log" appended to the test script's name.
+
diff --git a/tests/pkits/basic-certificate-revocation b/tests/pkits/basic-certificate-revocation
new file mode 100755
index 0000000..496a82c
--- /dev/null
+++ b/tests/pkits/basic-certificate-revocation
@@ -0,0 +1,31 @@
+#!/bin/sh
+# basic-certificate-revocation - PKITS Test 4.4 -*- sh -*-
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+. ${srcdir:-.}/common.sh || exit 2
+
+section=4.4
+description="Basic Certificate Revocation"
+info "Running $description tests"
+
+
+
+
+
+
+final_result
diff --git a/tests/pkits/certificate-policies b/tests/pkits/certificate-policies
new file mode 100755
index 0000000..f472201
--- /dev/null
+++ b/tests/pkits/certificate-policies
@@ -0,0 +1,31 @@
+#!/bin/sh
+# certificate-policies - PKITS Test 4.8 -*- sh -*-
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+. ${srcdir:-.}/common.sh || exit 2
+
+section=4.8
+description="Certificate Policies"
+info "Running $description tests"
+
+
+
+
+
+
+final_result
diff --git a/tests/pkits/common.sh b/tests/pkits/common.sh
new file mode 100644
index 0000000..697f28f
--- /dev/null
+++ b/tests/pkits/common.sh
@@ -0,0 +1,275 @@
+# common.sh - common defs for all tests -*- sh -*-
+# Copyright (C) 2004, 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+# reset some environment variables because we do not want to test locals
+LANG=C
+LANGUAGE=C
+LC_ALL=C
+export LANG LANGUAGE LC_ALL
+
+pgmname=`basename $0`
+
+if [ "$1" = "--debug" ]; then
+ debug=yes
+ set -x
+else
+ debug=
+fi
+[ -z "$srcdir" ] && srcdir="."
+[ -z "$top_srcdir" ] && top_srcdir=".."
+[ -z "$GPGSM" ] && GPGSM="../../sm/gpgsm"
+[ -z "$silent" ] && silent=no
+
+AWK=awk
+SCRATCH="scratch.$$.tmp"
+
+# We use this as the faked system time for certain tests.
+MYTIME="20080508T120000"
+
+
+if [ "$GNUPGHOME" != "`/bin/pwd`" ]; then
+ echo "inittests: please set GNUPGHOME to the tests/pkits directory" >&2
+ exit 1
+fi
+
+if [ -n "$GPG_AGENT_INFO" ]; then
+ echo "inittests: please unset GPG_AGENT_INFO" >&2
+ exit 1
+fi
+
+if [ -f "$srcdir/PKITS_data.tar.bz2" ]; then
+ :
+else
+ if [ "$pgmname" = "import-all-certs" ]; then
+ if [ "$silent" = "yes" ]; then tmp1="Note: "; tmp2=' '
+ else tmp1="- ____ "; tmp2="$tmp1"
+ fi
+ echo "${tmp1}PKITS_data.tar.bz2 is not installed"
+ echo "${tmp2}All tests will be skipped (this is not an error)"
+ fi
+ # Exit code 77 is used by the Makefile for skipping a tests.
+ exit 77
+fi
+
+#--------------------------------
+#------ utility functions -------
+#--------------------------------
+
+echo_n_init=no
+echo_n () {
+ if test "$echo_n_init" = "no"; then
+ if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ echo_n_n=
+ echo_n_c='
+'
+ else
+ echo_n_n='-n'
+ echo_n_c=
+ fi
+ else
+ echo_n_n=
+ echo_n_c='\c'
+ fi
+ echo_n_init=yes
+ fi
+ echo $echo_n_n "${1}$echo_n_c"
+}
+
+setup_output () {
+ if [ -z "$first_section_set" ]; then
+ first_section_set=$section
+ fi
+ section_out="$(echo $section)"
+ if [ -z "$section_out" ]; then
+ section_out="-"
+ fi
+}
+
+fatal () {
+ echo "$pgmname: fatal:" $* >&2
+ if [ "$silent" != "yes" ]; then
+ echo "$section_out ERROR: $* (fatal)"
+ fi
+ exit 1;
+}
+
+error () {
+ echo "$pgmname:" $* >&2
+ if [ "$silent" != "yes" ]; then
+ echo "$section_out ERROR: $*"
+ fi
+ exit 1
+}
+
+info () {
+ setup_output
+ echo "$pgmname:" $* >&2
+ if [ "$silent" != "yes" ]; then
+ echo "$section_out ____ $*"
+ fi
+}
+
+info_n () {
+ setup_output
+ echo_n "$pgmname:" $* >&2
+}
+
+pass () {
+ setup_output
+ echo "PASS: " $* >&2
+ pass_count=`expr ${pass_count} + 1`
+ if [ "$silent" != "yes" ]; then
+ echo_n "$section_out PASS"
+ if [ -n "$1" ]; then echo_n " $1"
+ elif [ -n "$description" ]; then echo_n " ($description)"
+ fi
+ echo
+ fi
+}
+
+fail () {
+ setup_output
+ echo "FAIL: " $* >&2
+ fail_count=`expr ${fail_count} + 1`
+ if [ "$silent" != "yes" ]; then
+ echo_n "$section_out FAIL"
+ if [ -n "$1" ]; then echo_n " $1"
+ elif [ -n "$description" ]; then echo_n " ($description)"
+ fi
+ echo
+ fi
+}
+
+skip () {
+ setup_output
+ echo "SKIP: " $* >&2
+ skip_count=`expr ${skip_count} + 1`
+ if [ "$silent" != "yes" ]; then
+ echo_n "$section_out SKIP"
+ if [ -n "$1" ]; then echo_n " $1"
+ elif [ -n "$description" ]; then echo_n " ($description)"
+ fi
+ echo
+ fi
+}
+
+unresolved () {
+ setup_output
+ echo "UNRESOLVED: " $* >&2
+ unresolved_count=`expr ${unresolved_count} + 1`
+ if [ "$silent" != "yes" ]; then
+ echo_n "$section_out UNRESOLVED"
+ if [ -n "$1" ]; then echo_n " $1"
+ elif [ -n "$description" ]; then echo_n " ($description)"
+ fi
+ echo
+ fi
+}
+
+
+final_result () {
+ section=$first_section_set
+ [ $pass_count = 0 ] || info "$pass_count tests passed"
+ [ $fail_count = 0 ] || info "$fail_count tests failed"
+ [ $skip_count = 0 ] || info "$unsupported_count tests skipped"
+ [ $unresolved_count = 0 ] || info "$unresolved_count tests unresolved"
+ [ -z "$debug" -a -f "$SCRATCH" ] && rm "$SCRATCH"
+ if [ $fail_count = 0 ]; then
+ info "all tests passed"
+ else
+ exit 1
+ fi
+}
+
+
+clean_homedir () {
+ [ -f pubring.kbx ] && rm pubring.kbx
+ if [ -d private-keys-v1.d ]; then
+ rm private-keys-v1.d/* 2>/dev/null || true
+ rmdir private-keys-v1.d
+ fi
+}
+
+start_test () {
+ section="$1"
+ description="$2"
+ test_status=none
+ echo "BEGIN TEST $section ($description)" >&2
+}
+
+end_test () {
+ case "$test_status" in
+ none) skip "($description) - test not implemented";;
+ pass) pass "($description)";;
+ fail) fail "($description)";;
+ setup) fail "($description) - setup failed";;
+ ns) skip "($description) - not supported";;
+ nys) skip "($description) - not yet supported";;
+ *) unresolved "$(description)";;
+ esac
+ echo "END TEST $section" >&2
+}
+
+set_status () {
+ if [ "$test_status" = "none" ]; then
+ test_status=$1
+ fi
+}
+
+need_cert () {
+ if [ "$2" = "--import-anyway" ]; then
+ if ! ${GPGSM} -q --debug-no-chain-validation --import certs/$1.crt
+ then
+ set_status setup
+ fi
+ else
+ if ! ${GPGSM} -q --import certs/$1.crt; then
+ set_status setup
+ fi
+ fi
+}
+
+need_crl () {
+ # CRL are not yet implemented
+ #set_status setup
+ :
+}
+
+
+
+set -e
+
+pass_count=0
+fail_count=0
+skip_count=0
+unresolved_count=0
+first_section_set=""
+section_out=""
+test_status=none
+
+# User settable variables
+section=""
+description=""
+
+
+#trap cleanup SIGHUP SIGINT SIGQUIT
+[ -z "$debug" ] && exec 2> ${pgmname}.log
+
+:
+# end
diff --git a/tests/pkits/delta-crls b/tests/pkits/delta-crls
new file mode 100755
index 0000000..2b91288
--- /dev/null
+++ b/tests/pkits/delta-crls
@@ -0,0 +1,31 @@
+#!/bin/sh
+# delta-crls - PKITS Test 4.15 -*- sh -*-
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+. ${srcdir:-.}/common.sh || exit 2
+
+section=4.15
+description="Delta-CRLs"
+info "Running $description tests"
+
+
+
+
+
+
+final_result
diff --git a/tests/pkits/distribution-points b/tests/pkits/distribution-points
new file mode 100755
index 0000000..2d59fcd
--- /dev/null
+++ b/tests/pkits/distribution-points
@@ -0,0 +1,31 @@
+#!/bin/sh
+# distribution-points - PKITS Test 4.14 -*- sh -*-
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+. ${srcdir:-.}/common.sh || exit 2
+
+section=4.14
+description="Distribution Points"
+info "Running $description tests"
+
+
+
+
+
+
+final_result
diff --git a/tests/pkits/import-all-certs b/tests/pkits/import-all-certs
new file mode 100755
index 0000000..51f3253
--- /dev/null
+++ b/tests/pkits/import-all-certs
@@ -0,0 +1,58 @@
+#!/bin/sh
+# import-all-certs - GnuPG import test -*- sh -*-
+# Copyright (C) 2004, 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+. ${srcdir:-.}/common.sh || exit 2
+
+section=6
+description="GnuPG Import"
+info "Running $description tests"
+
+while read flag dummy section name; do
+ case $flag in \#*) continue ;; esac
+ [ -z "$(echo $flag)" ] && continue;
+
+ description="import $name"
+ if ${GPGSM} -q --import certs/$name ; then
+ if [ "$flag" = 'p' ]; then
+ pass "importing certificate \`$name' succeeded"
+ elif [ "$flag" = 'f' ]; then
+ fail "importing certificate \`$name' succeeded"
+ elif [ "$flag" = '?' ]; then
+ unresolved "importing certificate \`$name' succeeded"
+ elif [ "$flag" = 'u' ]; then
+ skip "importing certificate \`$name' succeeded"
+ else
+ info "importing certificate \`$name' succeeded - (flag=$flag)"
+ fi
+ else
+ if [ "$flag" = 'p' ]; then
+ fail "importing certificate \`$name' failed"
+ elif [ "$flag" = 'f' ]; then
+ pass "importing certificate \`$name' failed"
+ elif [ "$flag" = '?' ]; then
+ unresolved "importing certificate \`$name' failed"
+ elif [ "$flag" = 'u' ]; then
+ skip "importing certificate \`$name' failed"
+ else
+ info "importing certificate \`$name' failed - (flag=$flag)"
+ fi
+ fi
+done < $srcdir/import-all-certs.data
+
+final_result
diff --git a/tests/pkits/import-all-certs.data b/tests/pkits/import-all-certs.data
new file mode 100644
index 0000000..e91b9f1
--- /dev/null
+++ b/tests/pkits/import-all-certs.data
@@ -0,0 +1,471 @@
+# The first column is for the basic import test, the second for a
+# validation test, the third is the section number and th foruth the
+# filename of the certificate.
+
+# Make sure that the root certificate is imported first
+p p 6.1.5.1 TrustAnchorRootCertificate.crt
+
+p p 6.1.5.168 AllCertificatesNoPoliciesTest2EE.crt
+p p 6.1.5.204 AllCertificatesSamePoliciesTest10EE.crt
+p p 6.1.5.211 AllCertificatesSamePoliciesTest13EE.crt
+p p 6.1.5.207 AllCertificatesanyPolicyTest11EE.crt
+p p 6.1.5.212 AnyPolicyTest14EE.crt
+p p 6.1.5.41 BadCRLIssuerNameCACert.crt
+p p 6.1.5.38 BadCRLSignatureCACert.crt
+f f 6.1.5.6 BadSignedCACert.crt
+p f 6.1.5.16 BadnotAfterDateCACert.crt
+
+# UTC: "470101120100Z" i.e. not before 2047-01-01
+p f 6.1.5.10 BadnotBeforeDateCACert.crt
+
+p p 6.1.5.88 BasicSelfIssuedCRLSigningKeyCACert.crt
+p p 6.1.5.90 BasicSelfIssuedCRLSigningKeyCRLCert.crt
+
+p p 6.1.5.76 BasicSelfIssuedNewKeyCACert.crt
+p p 6.1.5.78 BasicSelfIssuedNewKeyOldWithNewCACert.crt
+p p 6.1.5.81 BasicSelfIssuedOldKeyCACert.crt
+p p 6.1.5.83 BasicSelfIssuedOldKeyNewWithOldCACert.crt
+
+p p 6.1.5.218 CPSPointerQualifierTest20EE.crt
+
+p u 6.1.5.572 DSACACert.crt
+u u 6.1.5.575 DSAParametersInheritedCACert.crt
+
+p p 6.1.5.210 DifferentPoliciesTest12EE.crt
+p p 6.1.5.171 DifferentPoliciesTest3EE.crt
+p p 6.1.5.174 DifferentPoliciesTest4EE.crt
+p p 6.1.5.177 DifferentPoliciesTest5EE.crt
+p p 6.1.5.191 DifferentPoliciesTest7EE.crt
+p p 6.1.5.198 DifferentPoliciesTest8EE.crt
+p p 6.1.5.203 DifferentPoliciesTest9EE.crt
+p p 6.1.5.64 GeneralizedTimeCRLnextUpdateCACert.crt
+p p 6.1.5.3 GoodCACert.crt
+p p 6.1.5.172 GoodsubCACert.crt
+
+# gpgsm: critical certificate extension 2.5.29.33 (policyMappings)
+# is not supported
+p u 6.1.5.300 GoodsubCAPanyPolicyMapping1to2CACert.crt
+
+p f 6.1.5.43 InvalidBadCRLIssuerNameTest5EE.crt
+
+p f 6.1.5.40 InvalidBadCRLSignatureTest4EE.crt
+p f 6.1.5.93 InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt
+
+p f 6.1.5.94 InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt
+
+p f 6.1.5.87 InvalidBasicSelfIssuedNewWithOldTest5EE.crt
+
+p f 6.1.5.80 InvalidBasicSelfIssuedOldWithNewTest2EE.crt
+
+p f 6.1.5.8 InvalidCASignatureTest2EE.crt
+
+p f 6.1.5.18 InvalidCAnotAfterDateTest5EE.crt
+p f 6.1.5.12 InvalidCAnotBeforeDateTest1EE.crt
+p f 6.1.5.439 InvalidDNSnameConstraintsTest31EE.crt
+p f 6.1.5.443 InvalidDNSnameConstraintsTest33EE.crt
+p f 6.1.5.562 InvalidDNSnameConstraintsTest38EE.crt
+p f 6.1.5.434 InvalidDNandRFC822nameConstraintsTest28EE.crt
+p f 6.1.5.435 InvalidDNandRFC822nameConstraintsTest29EE.crt
+p f 6.1.5.399 InvalidDNnameConstraintsTest10EE.crt
+p f 6.1.5.403 InvalidDNnameConstraintsTest12EE.crt
+p f 6.1.5.406 InvalidDNnameConstraintsTest13EE.crt
+p f 6.1.5.410 InvalidDNnameConstraintsTest15EE.crt
+p f 6.1.5.411 InvalidDNnameConstraintsTest16EE.crt
+p f 6.1.5.414 InvalidDNnameConstraintsTest17EE.crt
+
+p f 6.1.5.418 InvalidDNnameConstraintsTest20EE.crt
+
+p f 6.1.5.383 InvalidDNnameConstraintsTest2EE.crt
+p f 6.1.5.384 InvalidDNnameConstraintsTest3EE.crt
+p f 6.1.5.392 InvalidDNnameConstraintsTest7EE.crt
+p f 6.1.5.395 InvalidDNnameConstraintsTest8EE.crt
+p f 6.1.5.396 InvalidDNnameConstraintsTest9EE.crt
+
+p u 6.1.5.578 InvalidDSASignatureTest6EE.crt
+
+p f 6.1.5.9 InvalidEESignatureTest3EE.crt
+
+p f 6.1.5.19 InvalidEEnotAfterDateTest6EE.crt
+p f 6.1.5.13 InvalidEEnotBeforeDateTest2EE.crt
+p f 6.1.5.500 InvalidIDPwithindirectCRLTest23EE.crt
+p f 6.1.5.504 InvalidIDPwithindirectCRLTest26EE.crt
+p f 6.1.5.75 InvalidLongSerialNumberTest18EE.crt
+p f 6.1.5.293 InvalidMappingFromanyPolicyTest7EE.crt
+p f 6.1.5.296 InvalidMappingToanyPolicyTest8EE.crt
+p f 6.1.5.33 InvalidMissingCRLTest1EE.crt
+p f 6.1.5.97 InvalidMissingbasicConstraintsTest1EE.crt
+p f 6.1.5.25 InvalidNameChainingOrderTest2EE.crt
+p f 6.1.5.22 InvalidNameChainingTest1EE.crt
+p f 6.1.5.70 InvalidNegativeSerialNumberTest15EE.crt
+p f 6.1.5.60 InvalidOldCRLnextUpdateTest11EE.crt
+p f 6.1.5.302 InvalidPolicyMappingTest10EE.crt
+p f 6.1.5.276 InvalidPolicyMappingTest2EE.crt
+p f 6.1.5.284 InvalidPolicyMappingTest4EE.crt
+p f 6.1.5.422 InvalidRFC822nameConstraintsTest22EE.crt
+p f 6.1.5.426 InvalidRFC822nameConstraintsTest24EE.crt
+p f 6.1.5.430 InvalidRFC822nameConstraintsTest26EE.crt
+p f 6.1.5.36 InvalidRevokedCATest2EE.crt
+p f 6.1.5.37 InvalidRevokedEETest3EE.crt
+
+p f 6.1.5.379 InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt
+
+p f 6.1.5.376 InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt
+p f 6.1.5.348 InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt
+p f 6.1.5.349 InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt
+p f 6.1.5.345 InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt
+p f 6.1.5.346 InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt
+p f 6.1.5.143 InvalidSelfIssuedpathLenConstraintTest16EE.crt
+p f 6.1.5.270 InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt
+p f 6.1.5.272 InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt
+
+p f 6.1.5.567 InvalidSeparateCertificateandCRLKeysTest20EE.crt
+p f 6.1.5.571 InvalidSeparateCertificateandCRLKeysTest21EE.crt
+
+p f 6.1.5.447 InvalidURInameConstraintsTest35EE.crt
+p f 6.1.5.451 InvalidURInameConstraintsTest37EE.crt
+p f 6.1.5.53 InvalidUnknownCRLEntryExtensionTest8EE.crt
+p f 6.1.5.57 InvalidUnknownCRLExtensionTest10EE.crt
+p f 6.1.5.56 InvalidUnknownCRLExtensionTest9EE.crt
+p f 6.1.5.546 InvalidUnknownCriticalCertificateExtensionTest2EE.crt
+p f 6.1.5.46 InvalidWrongCRLTest6EE.crt
+p f 6.1.5.100 InvalidcAFalseTest2EE.crt
+p f 6.1.5.103 InvalidcAFalseTest3EE.crt
+p f 6.1.5.505 InvalidcRLIssuerTest27EE.crt
+p f 6.1.5.519 InvalidcRLIssuerTest31EE.crt
+p f 6.1.5.520 InvalidcRLIssuerTest32EE.crt
+p f 6.1.5.522 InvalidcRLIssuerTest34EE.crt
+p f 6.1.5.523 InvalidcRLIssuerTest35EE.crt
+p f 6.1.5.526 InvaliddeltaCRLIndicatorNoBaseTest1EE.crt
+p f 6.1.5.544 InvaliddeltaCRLTest10EE.crt
+p f 6.1.5.531 InvaliddeltaCRLTest3EE.crt
+p f 6.1.5.532 InvaliddeltaCRLTest4EE.crt
+p f 6.1.5.534 InvaliddeltaCRLTest6EE.crt
+p f 6.1.5.540 InvaliddeltaCRLTest9EE.crt
+p f 6.1.5.455 InvaliddistributionPointTest2EE.crt
+p f 6.1.5.456 InvaliddistributionPointTest3EE.crt
+p f 6.1.5.461 InvaliddistributionPointTest6EE.crt
+p f 6.1.5.463 InvaliddistributionPointTest8EE.crt
+p f 6.1.5.464 InvaliddistributionPointTest9EE.crt
+p f 6.1.5.352 InvalidinhibitAnyPolicyTest1EE.crt
+p f 6.1.5.359 InvalidinhibitAnyPolicyTest4EE.crt
+p f 6.1.5.366 InvalidinhibitAnyPolicyTest5EE.crt
+p f 6.1.5.369 InvalidinhibitAnyPolicyTest6EE.crt
+p f 6.1.5.313 InvalidinhibitPolicyMappingTest1EE.crt
+p f 6.1.5.321 InvalidinhibitPolicyMappingTest3EE.crt
+p f 6.1.5.331 InvalidinhibitPolicyMappingTest5EE.crt
+p f 6.1.5.336 InvalidinhibitPolicyMappingTest6EE.crt
+p f 6.1.5.162 InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt
+p f 6.1.5.153 InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt
+p f 6.1.5.165 InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt
+p f 6.1.5.156 InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt
+p f 6.1.5.477 InvalidonlyContainsAttributeCertsTest14EE.crt
+p f 6.1.5.473 InvalidonlyContainsCACertsTest12EE.crt
+p f 6.1.5.470 InvalidonlyContainsUserCertsTest11EE.crt
+p f 6.1.5.481 InvalidonlySomeReasonsTest15EE.crt
+p f 6.1.5.482 InvalidonlySomeReasonsTest16EE.crt
+p f 6.1.5.486 InvalidonlySomeReasonsTest17EE.crt
+p f 6.1.5.495 InvalidonlySomeReasonsTest20EE.crt
+p f 6.1.5.496 InvalidonlySomeReasonsTest21EE.crt
+p f 6.1.5.122 InvalidpathLenConstraintTest10EE.crt
+p f 6.1.5.129 InvalidpathLenConstraintTest11EE.crt
+p f 6.1.5.130 InvalidpathLenConstraintTest12EE.crt
+p f 6.1.5.111 InvalidpathLenConstraintTest5EE.crt
+p f 6.1.5.112 InvalidpathLenConstraintTest6EE.crt
+p f 6.1.5.121 InvalidpathLenConstraintTest9EE.crt
+p f 6.1.5.63 Invalidpre2000CRLnextUpdateTest12EE.crt
+p f 6.1.5.20 Invalidpre2000UTCEEnotAfterDateTest7EE.crt
+p f 6.1.5.245 InvalidrequireExplicitPolicyTest3EE.crt
+p f 6.1.5.263 InvalidrequireExplicitPolicyTest5EE.crt
+p p 6.1.5.71 LongSerialNumberCACert.crt
+p p 6.1.5.273 Mapping1to2CACert.crt
+p p 6.1.5.291 MappingFromanyPolicyCACert.crt
+p p 6.1.5.294 MappingToanyPolicyCACert.crt
+p p 6.1.5.95 MissingbasicConstraintsCACert.crt
+p p 6.1.5.23 NameOrderingCACert.crt
+p p 6.1.5.67 NegativeSerialNumberCACert.crt
+p p 6.1.5.32 NoCRLCACert.crt
+p p 6.1.5.166 NoPoliciesCACert.crt
+p p 6.1.5.465 NoissuingDistributionPointCACert.crt
+p p 6.1.5.58 OldCRLnextUpdateCACert.crt
+p p 6.1.5.184 OverlappingPoliciesTest6EE.crt
+p p 6.1.5.277 P12Mapping1to3CACert.crt
+p p 6.1.5.279 P12Mapping1to3subCACert.crt
+p p 6.1.5.281 P12Mapping1to3subsubCACert.crt
+p p 6.1.5.285 P1Mapping1to234CACert.crt
+p p 6.1.5.287 P1Mapping1to234subCACert.crt
+p p 6.1.5.305 P1anyPolicyMapping1to2CACert.crt
+p p 6.1.5.297 PanyPolicyMapping1to2CACert.crt
+p p 6.1.5.178 PoliciesP1234CACert.crt
+p p 6.1.5.180 PoliciesP1234subCAP123Cert.crt
+p p 6.1.5.182 PoliciesP1234subsubCAP123P12Cert.crt
+p p 6.1.5.185 PoliciesP123CACert.crt
+p p 6.1.5.187 PoliciesP123subCAP12Cert.crt
+p p 6.1.5.189 PoliciesP123subsubCAP12P1Cert.crt
+p p 6.1.5.199 PoliciesP123subsubCAP12P2Cert.crt
+p p 6.1.5.201 PoliciesP123subsubsubCAP12P2P1Cert.crt
+p p 6.1.5.192 PoliciesP12CACert.crt
+p p 6.1.5.194 PoliciesP12subCAP1Cert.crt
+p p 6.1.5.196 PoliciesP12subsubCAP1P2Cert.crt
+p p 6.1.5.175 PoliciesP2subCA2Cert.crt
+p p 6.1.5.169 PoliciesP2subCACert.crt
+p p 6.1.5.208 PoliciesP3CACert.crt
+p p 6.1.5.547 RFC3280MandatoryAttributeTypesCACert.crt
+p p 6.1.5.550 RFC3280OptionalAttributeTypesCACert.crt
+p p 6.1.5.34 RevokedsubCACert.crt
+p p 6.1.5.556 RolloverfromPrintableStringtoUTF8StringCACert.crt
+p p 6.1.5.569 SeparateCertificateandCRLKeysCA2CRLSigningCert.crt
+p p 6.1.5.568 SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt
+p p 6.1.5.564 SeparateCertificateandCRLKeysCRLSigningCert.crt
+p p 6.1.5.563 SeparateCertificateandCRLKeysCertificateSigningCACert.crt
+p p 6.1.5.47 TwoCRLsCACert.crt
+p p 6.1.5.29 UIDCACert.crt
+p p 6.1.5.559 UTF8StringCaseInsensitiveMatchCACert.crt
+p p 6.1.5.553 UTF8StringEncodedNamesCACert.crt
+p p 6.1.5.51 UnknownCRLEntryExtensionCACert.crt
+p p 6.1.5.54 UnknownCRLExtensionCACert.crt
+p p 6.1.5.213 UserNoticeQualifierTest15EE.crt
+p p 6.1.5.214 UserNoticeQualifierTest16EE.crt
+p p 6.1.5.215 UserNoticeQualifierTest17EE.crt
+p p 6.1.5.216 UserNoticeQualifierTest18EE.crt
+p p 6.1.5.217 UserNoticeQualifierTest19EE.crt
+p p 6.1.5.92 ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt
+
+p p 6.1.5.85 ValidBasicSelfIssuedNewWithOldTest3EE.crt
+p p 6.1.5.86 ValidBasicSelfIssuedNewWithOldTest4EE.crt
+p p 6.1.5.79 ValidBasicSelfIssuedOldWithNewTest1EE.crt
+
+p p 6.1.5.5 ValidCertificatePathTest1EE.crt
+p p 6.1.5.438 ValidDNSnameConstraintsTest30EE.crt
+p p 6.1.5.442 ValidDNSnameConstraintsTest32EE.crt
+p p 6.1.5.433 ValidDNandRFC822nameConstraintsTest27EE.crt
+p p 6.1.5.400 ValidDNnameConstraintsTest11EE.crt
+
+# This certificate has an empty subject sequence. Our parser does not
+# support this yet and it is unlikely that gpgsm will be able to cope
+# with it at all.
+u u 6.1.5.407 ValidDNnameConstraintsTest14EE.crt
+
+p p 6.1.5.415 ValidDNnameConstraintsTest18EE.crt
+p p 6.1.5.417 ValidDNnameConstraintsTest19EE.crt
+
+p p 6.1.5.382 ValidDNnameConstraintsTest1EE.crt
+p p 6.1.5.385 ValidDNnameConstraintsTest4EE.crt
+p p 6.1.5.388 ValidDNnameConstraintsTest5EE.crt
+p p 6.1.5.391 ValidDNnameConstraintsTest6EE.crt
+
+u p 6.1.5.577 ValidDSAParameterInheritanceTest5EE.crt
+u p 6.1.5.574 ValidDSASignaturesTest4EE.crt
+
+p p 6.1.5.66 ValidGeneralizedTimeCRLnextUpdateTest13EE.crt
+p p 6.1.5.21 ValidGeneralizedTimenotAfterDateTest8EE.crt
+p p 6.1.5.15 ValidGeneralizedTimenotBeforeDateTest4EE.crt
+p p 6.1.5.499 ValidIDPwithindirectCRLTest22EE.crt
+p p 6.1.5.502 ValidIDPwithindirectCRLTest24EE.crt
+p p 6.1.5.503 ValidIDPwithindirectCRLTest25EE.crt
+p p 6.1.5.73 ValidLongSerialNumberTest16EE.crt
+p p 6.1.5.74 ValidLongSerialNumberTest17EE.crt
+p p 6.1.5.28 ValidNameChainingCapitalizationTest5EE.crt
+p p 6.1.5.26 ValidNameChainingWhitespaceTest3EE.crt
+p p 6.1.5.27 ValidNameChainingWhitespaceTest4EE.crt
+p p 6.1.5.31 ValidNameUIDsTest6EE.crt
+p p 6.1.5.69 ValidNegativeSerialNumberTest14EE.crt
+p p 6.1.5.467 ValidNoissuingDistributionPointTest10EE.crt
+p p 6.1.5.303 ValidPolicyMappingTest11EE.crt
+p p 6.1.5.304 ValidPolicyMappingTest12EE.crt
+p p 6.1.5.307 ValidPolicyMappingTest13EE.crt
+p p 6.1.5.308 ValidPolicyMappingTest14EE.crt
+p p 6.1.5.275 ValidPolicyMappingTest1EE.crt
+p p 6.1.5.283 ValidPolicyMappingTest3EE.crt
+p p 6.1.5.289 ValidPolicyMappingTest5EE.crt
+p p 6.1.5.290 ValidPolicyMappingTest6EE.crt
+p p 6.1.5.299 ValidPolicyMappingTest9EE.crt
+p p 6.1.5.549 ValidRFC3280MandatoryAttributeTypesTest7EE.crt
+p p 6.1.5.552 ValidRFC3280OptionalAttributeTypesTest8EE.crt
+p p 6.1.5.421 ValidRFC822nameConstraintsTest21EE.crt
+p p 6.1.5.425 ValidRFC822nameConstraintsTest23EE.crt
+p p 6.1.5.429 ValidRFC822nameConstraintsTest25EE.crt
+p p 6.1.5.558 ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt
+p p 6.1.5.373 ValidSelfIssuedinhibitAnyPolicyTest7EE.crt
+
+p p 6.1.5.378 ValidSelfIssuedinhibitAnyPolicyTest9EE.crt
+
+p p 6.1.5.342 ValidSelfIssuedinhibitPolicyMappingTest7EE.crt
+
+p ? 6.1.5.140 ValidSelfIssuedpathLenConstraintTest15EE.crt
+
+p p 6.1.5.150 ValidSelfIssuedpathLenConstraintTest17EE.crt
+
+p ? 6.1.5.267 ValidSelfIssuedrequireExplicitPolicyTest6EE.crt
+
+p ? 6.1.5.566 ValidSeparateCertificateandCRLKeysTest19EE.crt
+
+p p 6.1.5.50 ValidTwoCRLsTest7EE.crt
+p p 6.1.5.446 ValidURInameConstraintsTest34EE.crt
+p p 6.1.5.450 ValidURInameConstraintsTest36EE.crt
+p p 6.1.5.561 ValidUTF8StringCaseInsensitiveMatchTest11EE.crt
+p p 6.1.5.555 ValidUTF8StringEncodedNamesTest9EE.crt
+p p 6.1.5.545 ValidUnknownNotCriticalCertificateExtensionTest1EE.crt
+p p 6.1.5.106 ValidbasicConstraintsNotCriticalTest4EE.crt
+p p 6.1.5.510 ValidcRLIssuerTest28EE.crt
+p p 6.1.5.511 ValidcRLIssuerTest29EE.crt
+p p 6.1.5.515 ValidcRLIssuerTest30EE.crt
+p p 6.1.5.521 ValidcRLIssuerTest33EE.crt
+p p 6.1.5.530 ValiddeltaCRLTest2EE.crt
+p p 6.1.5.533 ValiddeltaCRLTest5EE.crt
+p p 6.1.5.535 ValiddeltaCRLTest7EE.crt
+p p 6.1.5.539 ValiddeltaCRLTest8EE.crt
+p p 6.1.5.454 ValiddistributionPointTest1EE.crt
+p p 6.1.5.457 ValiddistributionPointTest4EE.crt
+p p 6.1.5.460 ValiddistributionPointTest5EE.crt
+p p 6.1.5.462 ValiddistributionPointTest7EE.crt
+p p 6.1.5.353 ValidinhibitAnyPolicyTest2EE.crt
+p p 6.1.5.318 ValidinhibitPolicyMappingTest2EE.crt
+p p 6.1.5.322 ValidinhibitPolicyMappingTest4EE.crt
+p p 6.1.5.159 ValidkeyUsageNotCriticalTest3EE.crt
+p p 6.1.5.474 ValidonlyContainsCACertsTest13EE.crt
+p p 6.1.5.490 ValidonlySomeReasonsTest18EE.crt
+p p 6.1.5.494 ValidonlySomeReasonsTest19EE.crt
+p p 6.1.5.137 ValidpathLenConstraintTest13EE.crt
+p p 6.1.5.138 ValidpathLenConstraintTest14EE.crt
+p p 6.1.5.113 ValidpathLenConstraintTest7EE.crt
+p p 6.1.5.114 ValidpathLenConstraintTest8EE.crt
+p p 6.1.5.14 Validpre2000UTCnotBeforeDateTest3EE.crt
+p p 6.1.5.227 ValidrequireExplicitPolicyTest1EE.crt
+p p 6.1.5.236 ValidrequireExplicitPolicyTest2EE.crt
+p p 6.1.5.254 ValidrequireExplicitPolicyTest4EE.crt
+p p 6.1.5.44 WrongCRLCACert.crt
+p p 6.1.5.205 anyPolicyCACert.crt
+p p 6.1.5.98 basicConstraintsCriticalcAFalseCACert.crt
+p p 6.1.5.104 basicConstraintsNotCriticalCACert.crt
+p p 6.1.5.101 basicConstraintsNotCriticalcAFalseCACert.crt
+p p 6.1.5.527 deltaCRLCA1Cert.crt
+p p 6.1.5.536 deltaCRLCA2Cert.crt
+p p 6.1.5.541 deltaCRLCA3Cert.crt
+p p 6.1.5.524 deltaCRLIndicatorNoBaseCACert.crt
+p p 6.1.5.452 distributionPoint1CACert.crt
+p p 6.1.5.458 distributionPoint2CACert.crt
+p p 6.1.5.497 indirectCRLCA1Cert.crt
+p p 6.1.5.501 indirectCRLCA2Cert.crt
+p p 6.1.5.506 indirectCRLCA3Cert.crt
+p p 6.1.5.508 indirectCRLCA3cRLIssuerCert.crt
+p p 6.1.5.512 indirectCRLCA4Cert.crt
+p p 6.1.5.513 indirectCRLCA4cRLIssuerCert.crt
+p p 6.1.5.516 indirectCRLCA5Cert.crt
+p p 6.1.5.518 indirectCRLCA6Cert.crt
+p p 6.1.5.350 inhibitAnyPolicy0CACert.crt
+p p 6.1.5.354 inhibitAnyPolicy1CACert.crt
+
+p ? 6.1.5.370 inhibitAnyPolicy1SelfIssuedCACert.crt
+p ? 6.1.5.377 inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt
+
+p p 6.1.5.356 inhibitAnyPolicy1subCA1Cert.crt
+
+? ? 6.1.5.371 inhibitAnyPolicy1subCA2Cert.crt
+
+p p 6.1.5.367 inhibitAnyPolicy1subCAIAP5Cert.crt
+p p 6.1.5.374 inhibitAnyPolicy1subsubCA2Cert.crt
+p p 6.1.5.360 inhibitAnyPolicy5CACert.crt
+p p 6.1.5.362 inhibitAnyPolicy5subCACert.crt
+p p 6.1.5.364 inhibitAnyPolicy5subsubCACert.crt
+p p 6.1.5.358 inhibitAnyPolicyTest3EE.crt
+p p 6.1.5.309 inhibitPolicyMapping0CACert.crt
+p p 6.1.5.311 inhibitPolicyMapping0subCACert.crt
+p p 6.1.5.314 inhibitPolicyMapping1P12CACert.crt
+p p 6.1.5.316 inhibitPolicyMapping1P12subCACert.crt
+p p 6.1.5.332 inhibitPolicyMapping1P12subCAIPM5Cert.crt
+p p 6.1.5.319 inhibitPolicyMapping1P12subsubCACert.crt
+p p 6.1.5.334 inhibitPolicyMapping1P12subsubCAIPM5Cert.crt
+p p 6.1.5.337 inhibitPolicyMapping1P1CACert.crt
+
+# For yet unknown reasons gpgsm claims a bad signature.
+? ? 6.1.5.339 inhibitPolicyMapping1P1SelfIssuedCACert.crt
+? ? 6.1.5.347 inhibitPolicyMapping1P1SelfIssuedsubCACert.crt
+? ? 6.1.5.340 inhibitPolicyMapping1P1subCACert.crt
+
+p p 6.1.5.343 inhibitPolicyMapping1P1subsubCACert.crt
+p p 6.1.5.323 inhibitPolicyMapping5CACert.crt
+p p 6.1.5.325 inhibitPolicyMapping5subCACert.crt
+p p 6.1.5.327 inhibitPolicyMapping5subsubCACert.crt
+p p 6.1.5.329 inhibitPolicyMapping5subsubsubCACert.crt
+p p 6.1.5.160 keyUsageCriticalcRLSignFalseCACert.crt
+p p 6.1.5.151 keyUsageCriticalkeyCertSignFalseCACert.crt
+p p 6.1.5.157 keyUsageNotCriticalCACert.crt
+p p 6.1.5.163 keyUsageNotCriticalcRLSignFalseCACert.crt
+p p 6.1.5.154 keyUsageNotCriticalkeyCertSignFalseCACert.crt
+p p 6.1.5.380 nameConstraintsDN1CACert.crt
+
+? ? 6.1.5.416 nameConstraintsDN1SelfIssuedCACert.crt
+
+p p 6.1.5.401 nameConstraintsDN1subCA1Cert.crt
+p p 6.1.5.404 nameConstraintsDN1subCA2Cert.crt
+p p 6.1.5.431 nameConstraintsDN1subCA3Cert.crt
+p p 6.1.5.386 nameConstraintsDN2CACert.crt
+p p 6.1.5.389 nameConstraintsDN3CACert.crt
+p p 6.1.5.408 nameConstraintsDN3subCA1Cert.crt
+p p 6.1.5.412 nameConstraintsDN3subCA2Cert.crt
+p p 6.1.5.393 nameConstraintsDN4CACert.crt
+p p 6.1.5.397 nameConstraintsDN5CACert.crt
+p p 6.1.5.436 nameConstraintsDNS1CACert.crt
+p p 6.1.5.440 nameConstraintsDNS2CACert.crt
+p p 6.1.5.419 nameConstraintsRFC822CA1Cert.crt
+p p 6.1.5.423 nameConstraintsRFC822CA2Cert.crt
+p p 6.1.5.427 nameConstraintsRFC822CA3Cert.crt
+p p 6.1.5.444 nameConstraintsURI1CACert.crt
+p p 6.1.5.448 nameConstraintsURI2CACert.crt
+p p 6.1.5.475 onlyContainsAttributeCertsCACert.crt
+p p 6.1.5.471 onlyContainsCACertsCACert.crt
+p p 6.1.5.468 onlyContainsUserCertsCACert.crt
+p p 6.1.5.478 onlySomeReasonsCA1Cert.crt
+p p 6.1.5.483 onlySomeReasonsCA2Cert.crt
+p p 6.1.5.487 onlySomeReasonsCA3Cert.crt
+p p 6.1.5.491 onlySomeReasonsCA4Cert.crt
+p p 6.1.5.107 pathLenConstraint0CACert.crt
+
+? ? 6.1.5.139 pathLenConstraint0SelfIssuedCACert.crt
+? ? 6.1.5.141 pathLenConstraint0subCA2Cert.crt
+
+p p 6.1.5.109 pathLenConstraint0subCACert.crt
+p p 6.1.5.144 pathLenConstraint1CACert.crt
+
+? ? 6.1.5.146 pathLenConstraint1SelfIssuedCACert.crt
+? ? 6.1.5.149 pathLenConstraint1SelfIssuedsubCACert.crt
+? ? 6.1.5.147 pathLenConstraint1subCACert.crt
+
+p p 6.1.5.115 pathLenConstraint6CACert.crt
+p p 6.1.5.117 pathLenConstraint6subCA0Cert.crt
+p p 6.1.5.123 pathLenConstraint6subCA1Cert.crt
+p p 6.1.5.131 pathLenConstraint6subCA4Cert.crt
+p p 6.1.5.119 pathLenConstraint6subsubCA00Cert.crt
+p p 6.1.5.125 pathLenConstraint6subsubCA11Cert.crt
+p p 6.1.5.133 pathLenConstraint6subsubCA41Cert.crt
+p p 6.1.5.127 pathLenConstraint6subsubsubCA11XCert.crt
+p p 6.1.5.135 pathLenConstraint6subsubsubCA41XCert.crt
+p p 6.1.5.61 pre2000CRLnextUpdateCACert.crt
+p p 6.1.5.246 requireExplicitPolicy0CACert.crt
+p p 6.1.5.248 requireExplicitPolicy0subCACert.crt
+p p 6.1.5.250 requireExplicitPolicy0subsubCACert.crt
+p p 6.1.5.252 requireExplicitPolicy0subsubsubCACert.crt
+p p 6.1.5.219 requireExplicitPolicy10CACert.crt
+p p 6.1.5.221 requireExplicitPolicy10subCACert.crt
+p p 6.1.5.223 requireExplicitPolicy10subsubCACert.crt
+p p 6.1.5.225 requireExplicitPolicy10subsubsubCACert.crt
+p p 6.1.5.264 requireExplicitPolicy2CACert.crt
+
+# For yet unknown reasons gpgsm claims a bad signature.
+? ? 6.1.5.266 requireExplicitPolicy2SelfIssuedCACert.crt
+? ? 6.1.5.271 requireExplicitPolicy2SelfIssuedsubCACert.crt
+? ? 6.1.5.268 requireExplicitPolicy2subCACert.crt
+
+p p 6.1.5.237 requireExplicitPolicy4CACert.crt
+p p 6.1.5.239 requireExplicitPolicy4subCACert.crt
+p p 6.1.5.241 requireExplicitPolicy4subsubCACert.crt
+p p 6.1.5.243 requireExplicitPolicy4subsubsubCACert.crt
+p p 6.1.5.228 requireExplicitPolicy5CACert.crt
+p p 6.1.5.230 requireExplicitPolicy5subCACert.crt
+p p 6.1.5.232 requireExplicitPolicy5subsubCACert.crt
+p p 6.1.5.234 requireExplicitPolicy5subsubsubCACert.crt
+p p 6.1.5.255 requireExplicitPolicy7CACert.crt
+p p 6.1.5.257 requireExplicitPolicy7subCARE2Cert.crt
+p p 6.1.5.259 requireExplicitPolicy7subsubCARE2RE4Cert.crt
+p p 6.1.5.261 requireExplicitPolicy7subsubsubCARE2RE4Cert.crt
+
diff --git a/tests/pkits/inhibit-any-policy b/tests/pkits/inhibit-any-policy
new file mode 100755
index 0000000..5e625e2
--- /dev/null
+++ b/tests/pkits/inhibit-any-policy
@@ -0,0 +1,31 @@
+#!/bin/sh
+# inhibit-any-policy - PKITS Test 4.12 -*- sh -*-
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+. ${srcdir:-.}/common.sh || exit 2
+
+section=4.12
+description="Inhibit Any Policy"
+info "Running $description tests"
+
+
+
+
+
+
+final_result
diff --git a/tests/pkits/inhibit-policy-mapping b/tests/pkits/inhibit-policy-mapping
new file mode 100755
index 0000000..1da5f35
--- /dev/null
+++ b/tests/pkits/inhibit-policy-mapping
@@ -0,0 +1,31 @@
+#!/bin/sh
+# inhibit-policy-mapping - PKITS Test 4.11 -*- sh -*-
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+. ${srcdir:-.}/common.sh || exit 2
+
+section=4.11
+description="Inhibit Policy Mapping"
+info "Running $description tests"
+
+
+
+
+
+
+final_result
diff --git a/tests/pkits/inittests b/tests/pkits/inittests
new file mode 100755
index 0000000..deb1854
--- /dev/null
+++ b/tests/pkits/inittests
@@ -0,0 +1,109 @@
+#!/bin/sh
+# Copyright (C) 2004 Free Software Foundation, Inc. -*- sh -*-
+#
+# This file is free software; as a special exception the author gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+set -e
+
+
+clean_files='
+ReadMe.txt pkits.ldif pkits.schema
+gpgsm.conf gpg-agent.conf trustlist.txt policies.txt pubring.kbx
+msg msg.sig msg.unsig
+'
+
+[ -z "$srcdir" ] && srcdir=.
+[ -z "$GPGSM" ] && GPGSM=../../sm/gpgsm
+
+#if [ -f $srcdir/README ] \
+# && grep tests/pkits/README README >/dev/null 2>&1; then
+# :
+#else
+# # During make distclean the Makefile has already been removed,
+# # so we need this extra test.
+# if ! grep gnupg-test-pkits-directory testdir.stamp >/dev/null 2>&1; then
+# echo "inittests: please cd to the tests/pkits directory first" >&2
+# exit 1
+# fi
+#fi
+
+if [ "$1" = "--clean" ]; then
+ if [ -d private-keys-v1.d ]; then
+ rm private-keys-v1.d/* 2>/dev/null || true
+ rmdir private-keys-v1.d
+ fi
+ rm ${clean_files} testdir.stamp 2>/dev/null || true
+ for i in certs certpairs crls pkcs12 smime; do
+ if [ -d $i ]; then
+ rm $i/* 2>/dev/null || true
+ rmdir $i
+ fi
+ done
+ exit 0
+fi
+
+if [ "$GNUPGHOME" != "`/bin/pwd`" ]; then
+ echo "inittests: please set GNUPGHOME to the tests/pkits directory" >&2
+ exit 1
+fi
+
+if [ -n "$GPG_AGENT_INFO" ]; then
+ echo "inittests: please unset GPG_AGENT_INFO" >&2
+ exit 1
+fi
+
+if test -f "$srcdir/PKITS_data.tar.bz2"; then
+ if ! bunzip2 -c "$srcdir/PKITS_data.tar.bz2" | tar xf - ; then
+ echo "inittests: failed to untar the test data" >&2
+ exit 1
+ fi
+fi
+
+# A stamp file used with --clean
+echo gnupg-test-pkits-directory > testdir.stamp
+
+
+# Create the configuration scripts
+cat > gpgsm.conf <<EOF
+no-secmem-warning
+no-greeting
+batch
+disable-crl-checks
+disable-dirmngr
+agent-program ../../agent/gpg-agent
+no-common-certs-import
+EOF
+
+# The set of NIST test policies which should be used if anyPolicy is
+# not supported.
+cat > policies.txt <<EOF
+2.16.840.1.101.3.2.1.48.1
+2.16.840.1.101.3.2.1.48.2
+2.16.840.1.101.3.2.1.48.3
+2.16.840.1.101.3.2.1.48.4
+2.16.840.1.101.3.2.1.48.5
+2.16.840.1.101.3.2.1.48.6
+EOF
+
+# Fixme: we need to write a dummy pinentry program
+cat > gpg-agent.conf <<EOF
+no-grab
+disable-scdaemon
+EOF
+
+# Mark the root CA trusted
+cat > trustlist.txt <<EOF
+# /CN=Trust Anchor/O=Test Certificates/C=US
+66:8A:47:56:A2:DC:88:FF:DA:B8:95:E1:3C:63:37:55:5F:0A:F7:BF S
+EOF
+
+# Define the standard policies as NIST test-policy-1
+#cat >policies.txt <<EOF
+#2.16.840.1.101.3.2.1.48.1
+#EOF
diff --git a/tests/pkits/key-usage b/tests/pkits/key-usage
new file mode 100755
index 0000000..6e10bb9
--- /dev/null
+++ b/tests/pkits/key-usage
@@ -0,0 +1,28 @@
+#!/bin/sh
+# key-usage - PKITS Test 4.7 -*- sh -*-
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+. ${srcdir:-.}/common.sh || exit 2
+
+section=4.7
+description="Key Usage"
+info "Running $description tests"
+
+
+
+final_result
diff --git a/tests/pkits/name-constraints b/tests/pkits/name-constraints
new file mode 100755
index 0000000..8e36c28
--- /dev/null
+++ b/tests/pkits/name-constraints
@@ -0,0 +1,31 @@
+#!/bin/sh
+# name-constraints - PKITS Test 4.13 -*- sh -*-
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+. ${srcdir:-.}/common.sh || exit 2
+
+section=4.13
+description="Name Constraints"
+info "Running $description tests"
+
+
+
+
+
+
+final_result
diff --git a/tests/pkits/policy-mappings b/tests/pkits/policy-mappings
new file mode 100755
index 0000000..8ce9ee8
--- /dev/null
+++ b/tests/pkits/policy-mappings
@@ -0,0 +1,31 @@
+#!/bin/sh
+# policy-mappings - PKITS Test 4.10 -*- sh -*-
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+. ${srcdir:-.}/common.sh || exit 2
+
+section=4.10
+description="Policy Mappings"
+info "Running $description tests"
+
+
+
+
+
+
+final_result
diff --git a/tests/pkits/private-certificate-extensions b/tests/pkits/private-certificate-extensions
new file mode 100755
index 0000000..43f3425
--- /dev/null
+++ b/tests/pkits/private-certificate-extensions
@@ -0,0 +1,31 @@
+#!/bin/sh
+# private-certificate-extensions - PKITS Test 4.16 -*- sh -*-
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+. ${srcdir:-.}/common.sh || exit 2
+
+section=4.16
+description="Private Certificate Extensions"
+info "Running $description tests"
+
+
+
+
+
+
+final_result
diff --git a/tests/pkits/require-explicit-policy b/tests/pkits/require-explicit-policy
new file mode 100755
index 0000000..ceb87bd
--- /dev/null
+++ b/tests/pkits/require-explicit-policy
@@ -0,0 +1,31 @@
+#!/bin/sh
+# require-explicit-policy - PKITS Test 4.9 -*- sh -*-
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+. ${srcdir:-.}/common.sh || exit 2
+
+section=4.9
+description="Require Explicit Policy"
+info "Running $description tests"
+
+
+
+
+
+
+final_result
diff --git a/tests/pkits/runtest b/tests/pkits/runtest
new file mode 100755
index 0000000..f054a34
--- /dev/null
+++ b/tests/pkits/runtest
@@ -0,0 +1,4 @@
+#!/bin/sh
+[ -x "$1" ] && exec $1 $2
+exec sh $1 $2
+
diff --git a/tests/pkits/signature-verification b/tests/pkits/signature-verification
new file mode 100755
index 0000000..7765371
--- /dev/null
+++ b/tests/pkits/signature-verification
@@ -0,0 +1,167 @@
+#!/bin/sh
+# signature-verification - PKITS Test 4.1 -*- sh -*-
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+. ${srcdir:-.}/common.sh || exit 2
+
+section=4.1
+description="Signature Verification"
+info "Running $description tests"
+
+
+start_test 4.1.1 "Valid Signatures Test1"
+# The purpose of this test is to verify an application's ability to
+# name chain, signature chain, and check validity dates, on
+# certificates in a certification path. It also tests processing of
+# the basic constraints and key usage extensions in intermediate
+# certificates.
+clean_homedir
+need_cert TrustAnchorRootCertificate
+need_crl TrustAnchorRootCRL
+need_cert GoodCACert
+need_crl GoodCACRL
+need_cert ValidCertificatePathTest1EE
+if $GPGSM --with-colons --with-validation --list-key 0x126B7002 >$SCRATCH; then
+ tmp=$($AWK -F: '$1 == "crt" {any=1; print $2};
+ END {if(!any) print "error"}' $SCRATCH)
+ [ -n "$tmp" ] && set_status fail
+else
+ set_status fail
+fi
+if [ "$test_status" = "none" ]; then
+ if sed '1,/^.$/d' smime/SignedValidSignaturesTest1.eml \
+ | $GPGSM --verify --assume-base64 --status-fd 1 \
+ | grep TRUST_FULLY >/dev/null; then
+ set_status pass
+ else
+ set_status fail
+ fi
+fi
+end_test
+
+
+
+start_test 4.1.2 "Invalid CA Signatures Test2"
+# The purpose of this test is to verify an application's ability to
+# recognize an invalid signature on an intermediate certificate in a
+# certification path.
+clean_homedir
+need_cert TrustAnchorRootCertificate
+need_crl TrustAnchorRootCRL
+need_cert BadSignedCACert --import-anyway
+need_crl BadSignedCACRL
+need_cert InvalidCASignatureTest2EE --import-anyway
+if $GPGSM --with-colons --with-validation --list-key 0xD667FE3C >$SCRATCH; then
+ tmp=$($AWK -F: '$1 == "crt" {any=1; print $2};
+ END {if(!any) print "error"}' $SCRATCH)
+ [ "$tmp" = "i" ] || set_status fail
+else
+ set_status fail
+fi
+if [ "$test_status" = "none" ]; then
+ if sed '1,/^.$/d' smime/SignedInvalidCASignatureTest2.eml \
+ | $GPGSM --verify --assume-base64 --status-fd 1 \
+ | grep TRUST_NEVER >/dev/null; then
+ set_status pass
+ else
+ set_status fail
+ fi
+fi
+end_test
+
+
+
+start_test 4.1.3 "Invalid EE Signature Test3"
+# The purpose of this test is to verify an application's ability to
+# recognize an invalid signature on an end entity certificate in a
+# certification path.
+clean_homedir
+need_cert TrustAnchorRootCertificate
+need_crl TrustAnchorRootCRL
+need_cert GoodCACert
+need_crl GoodCACRL
+need_cert InvalidEESignatureTest3EE --import-anyway
+if $GPGSM --with-colons --with-validation --list-key 0x42E1AEE3 >$SCRATCH; then
+ tmp=$($AWK -F: '$1 == "crt" {any=1; print $2};
+ END {if(!any) print "error"}' $SCRATCH)
+ [ "$tmp" = "i" ] || set_status fail
+else
+ set_status fail
+fi
+if [ "$test_status" = "none" ]; then
+ if sed '1,/^.$/d' smime/SignedInvalidEESignatureTest3.eml \
+ | $GPGSM --verify --assume-base64 --status-fd 1 \
+ | grep TRUST_NEVER >/dev/null; then
+ set_status pass
+ else
+ set_status fail
+ fi
+fi
+end_test
+
+
+start_test 4.1.4 "Valid DSA Signatures Test4"
+# The purpose of this test is to verify an application's ability to
+# validate certificate in which DSA signatures are used. The
+# intermediate CA and the end entity have DSA key pairs.
+clean_homedir
+need_cert TrustAnchorRootCertificate
+need_crl TrustAnchorRootCRL
+need_cert DSACACert
+need_crl DSACACRL
+need_cert ValidDSASignaturesTest4EE
+if $GPGSM --with-colons --with-validation --list-key 0x820A72B8 >$SCRATCH; then
+ tmp=$($AWK -F: '$1 == "crt" {any=1; print $2};
+ END {if(!any) print "error"}' $SCRATCH)
+ [ -n "$tmp" ] && set_status fail
+else
+ set_status fail
+fi
+if [ "$test_status" = "none" ]; then
+ # Note: This S/MIME file uses LF and not CR,LF. */
+ if sed '1,/^$/d' smime/SignedValidDSASignaturesTest4.eml \
+ | $GPGSM --verify --assume-base64 --status-fd 1 \
+ | grep TRUST_FULLY >/dev/null; then
+ set_status pass
+ else
+ set_status fail
+ fi
+fi
+end_test
+
+
+start_test 4.1.5 "Valid DSA Parameter Inheritance Test5"
+# The purpose of this test is to verify an application's ability to
+# validate DSA signatures when the DSA parameters are not included in
+# a certificate and need to be inherited from a previous certificate
+# in the path. The intermediate CAs and the end entity have DSA key
+# pairs.
+set_status nys
+end_test
+
+
+start_test 4.1.6 "Invalid DSA Signature Test6"
+# The purpose of this test is to verify an application's ability to
+# determine when a DSA signature is invalid. The intermediate CA and
+# the end entity have DSA key pairs.
+set_status nys
+end_test
+
+
+
+final_result
diff --git a/tests/pkits/validate-all-certs b/tests/pkits/validate-all-certs
new file mode 100755
index 0000000..b9da579
--- /dev/null
+++ b/tests/pkits/validate-all-certs
@@ -0,0 +1,59 @@
+#!/bin/sh
+# validate-all-certs - GnuPG import and validate tests -*- sh -*-
+# Copyright (C) 2004, 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+. ${srcdir:-.}/common.sh || exit 2
+
+section=6
+description="GnuPG Import with Validation"
+info "Running $description tests"
+
+while read dummy flag section name; do
+ case $dummy in \#*) continue;; esac
+ [ -z "$(echo $dummy)" ] && continue;
+
+ description="import and validate $name"
+ if ${GPGSM} -q --import --with-validation --disable-crl-checks \
+ certs/$name ; then
+ if [ "$flag" = 'p' ]; then
+ pass "validating certificate \`$name' succeeded"
+ elif [ "$flag" = 'f' ]; then
+ fail "validating certificate \`$name' succeeded"
+ elif [ "$flag" = '?' ]; then
+ unresolved "validating certificate \`$name' succeeded"
+ elif [ "$flag" = 'u' ]; then
+ skip "validating certificate \`$name' succeeded"
+ else
+ info "validating certificate \`$name' succeeded - (flag=$flag)"
+ fi
+ else
+ if [ "$flag" = 'p' ]; then
+ fail "validating certificate \`$name' failed"
+ elif [ "$flag" = 'f' ]; then
+ pass "validating certificate \`$name' failed"
+ elif [ "$flag" = '?' ]; then
+ unresolved "validating certificate \`$name' failed"
+ elif [ "$flag" = 'u' ]; then
+ skip "validating certificate \`$name' failed"
+ else
+ info "validating certificate \`$name' failed - (flag=$flag)"
+ fi
+ fi
+done < $srcdir/import-all-certs.data
+
+final_result
diff --git a/tests/pkits/validity-periods b/tests/pkits/validity-periods
new file mode 100755
index 0000000..90f1764
--- /dev/null
+++ b/tests/pkits/validity-periods
@@ -0,0 +1,218 @@
+#!/bin/sh
+# validity-periods - PKITS Test 4.2 -*- sh -*-
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+. ${srcdir:-.}/common.sh || exit 2
+
+section=4.2
+description="Validity Periods"
+info "Running $description tests"
+
+start_test 4.2.1 "Invalid CA notBefore Date Test1"
+# In this test, the intermediate certificate's notBefore date is after
+# the current date.
+clean_homedir
+need_cert TrustAnchorRootCertificate
+need_crl TrustAnchorRootCRL
+need_cert BadnotBeforeDateCACert
+need_crl BadnotBeforeDateCACRL
+need_cert InvalidCAnotBeforeDateTest1EE
+if $GPGSM --faked-system-time $MYTIME \
+ --with-colons --with-validation --list-key 0x459ADD33 >$SCRATCH; then
+ tmp=$($AWK -F: '$1 == "crt" {any=1; print $2};
+ END {if(!any) print "error"}' $SCRATCH)
+ [ "$tmp" = "i" ] || set_status fail
+else
+ set_status fail
+fi
+if [ "$test_status" = "none" ]; then
+ if sed '1,/^.$/d' smime/SignedInvalidCAnotBeforeDateTest1.eml \
+ | $GPGSM --faked-system-time $MYTIME \
+ --verify --assume-base64 --status-fd 1 --logger-fd 1 \
+ | tee $SCRATCH \
+ | grep TRUST_UNDEFINED >/dev/null; then
+ if grep 'intermediate certificate not yet valid' $SCRATCH >/dev/null \
+ && grep 'invalid certification chain: Certificate too young' \
+ $SCRATCH >/dev/null
+ then
+ set_status pass
+ fi
+ fi
+ set_status fail
+fi
+end_test
+
+
+start_test 4.2.2 "Invalid EE notBefore Date Test2"
+# In this test, the end entity certificate's notBefore date is after
+# the current date.
+
+# Procedure: Validate Invalid EE notBefore Date Test2 EE using the
+# default settings or open and verify Signed Test Message 6.2.2.5
+# using the default settings.
+
+# Expected Result: The path should not validate successfully as the
+# notBefore date in the end entity certificate is after the current
+# date.
+
+# Certification Path: The certification path is composed of the
+# following objects: Trust Anchor Root Certificate, Trust Anchor
+# Root CRL Good CA Cert, Good CA CRL Invalid EE notBefore Date
+# Test2 EE
+
+end_test
+
+
+
+start_test 4.2.3 "Valid pre2000 UTC notBefore Date Test3"
+# In this test, the end entity certificate's notBefore date is set to
+# 1950 and is encoded in UTCTime.
+#
+# Procedure: Validate Valid pre2000 UTC notBefore Date Test3 EE
+# using the default settings or open and
+# verify Signed Test Message 6.2.2.6 using
+# the default settings.
+#
+# Expected Result: The path should validate successfully as the
+# notBefore date in the end entity
+# certificate is before the current date.
+#
+# Certification Path: The certification path is composed of the
+# following objects: Trust Anchor Root Certificate,
+# Trust Anchor Root CRL Good CA Cert, Good CA CRL Valid
+# pre2000 UTC notBefore Date Test3 EE
+#
+end_test
+
+
+
+start_test 4.2.4 "Valid GeneralizedTime notBefore Date Test4"
+# In this test, the end entity certificate's notBefore date is
+# specified in GeneralizedTime.
+#
+# Procedure: Validate Valid GeneralizedTime notBefore Date Test4 EE
+# using the default settings or open and
+# verify Signed Test Message 6.2.2.7 using
+# the default settings.
+#
+# Expected Result: The path should validate successfully.
+#
+# Certification Path:
+# The certification path is composed of the following objects:
+# Trust Anchor Root Certificate, Trust Anchor Root CRL
+# Good CA Cert, Good CA CRL
+# Valid GeneralizedTime notBefore Date Test4 EE
+#
+end_test
+
+
+
+start_test 4.2.5 "Invalid CA notAfter Date Test5"
+# In this test, the intermediate certificate's notAfter date is before
+# the current date.
+
+# Procedure: Validate Invalid CA notAfter Date Test5 EE using the
+# default settings or open and verify
+# Signed Test Message 6.2.2.8 using the
+# default settings.
+#
+# Expected Result: The path should not validate successfully as the
+# notAfter date in the intermediate
+# certificate is before the current date.
+#
+# Certification Path: The certification path is composed of the
+# following objects:
+#
+# Trust Anchor Root Certificate, Trust Anchor Root CRL
+# Bad notAfter Date CA Cert, Bad notAfter Date CA CRL
+# Invalid CA notAfter Date Test5 EE
+#
+end_test
+
+
+start_test 4.2.6 "Invalid EE notAfter Date Test6"
+# In this test, the end entity certificate's notAfter date is before
+# the current date.
+
+# Procedure: Validate Invalid EE notAfter Date Test6 EE using the
+# default settings or open and verify
+# Signed Test Message 6.2.2.9 using the
+# default settings.
+#
+# Expected Result: The path should not validate successfully as the
+# notAfter date in the end certificate is
+# before the current date.
+#
+# Certification Path: The certification path is composed of the
+# following objects:
+# Trust Anchor Root Certificate, Trust Anchor Root CRL
+# Good CA Cert, Good CA CRL
+# Invalid EE notAfter Date Test6 EE
+
+end_test
+
+
+start_test 4.2.7 "Invalid pre2000 UTC EE notAfter Date Test7"
+# In this test, the end entity certificate's notAfter date is 1999 and
+# is encoded in UTCTime.
+
+# Procedure: Validate Invalid pre2000 UTC EE notAfter Date Test7 EE
+# using the default settings or open and
+# verify Signed Test Message 6.2.2.10 using
+# the default settings.
+#
+# Expected Result: The path should not validate successfully as the
+# notAfter date in the end certificate is
+# before the current date.
+#
+#
+# Certification Path: The certification path is composed of the
+# following objects:
+#
+# Trust Anchor Root Certificate, Trust Anchor Root CRL
+# Good CA Cert, Good CA CRL
+# Invalid pre2000 UTC EE notAfter Date Test7 EE
+
+end_test
+
+
+
+start_test 4.2.8 "Valid GeneralizedTime notAfter Date Test8"
+# In this test, the end entity certificate's notAfter date is 2050 and
+# is encoded in GeneralizedTime.
+
+# Procedure: Validate Valid GeneralizedTime notAfter Date Test8 EE
+# using the default settings or open and
+# verify Signed Test Message 6.2.2.11 using
+# the default settings.
+#
+# Expected Result: The path should validate successfully as the
+# notAfter date in the end certificate is
+# after the current date.
+#
+#
+# Trust Anchor Root Certificate, Trust Anchor Root CRL
+# Good CA Cert, Good CA CRL
+# Valid GeneralizedTime notAfter Date Test8 EE
+
+end_test
+
+
+
+
+final_result
diff --git a/tests/pkits/verifying-basic-constraints b/tests/pkits/verifying-basic-constraints
new file mode 100755
index 0000000..0e052f3
--- /dev/null
+++ b/tests/pkits/verifying-basic-constraints
@@ -0,0 +1,31 @@
+#!/bin/sh
+# verifying-basic-constraints - PKITS Test 4.6 -*- sh -*-
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+. ${srcdir:-.}/common.sh || exit 2
+
+section=4.6
+description="Verifying Basic Constraints"
+info "Running $description tests"
+
+
+
+
+
+
+final_result
diff --git a/tests/pkits/verifying-name-chaining b/tests/pkits/verifying-name-chaining
new file mode 100755
index 0000000..9bdbb59
--- /dev/null
+++ b/tests/pkits/verifying-name-chaining
@@ -0,0 +1,31 @@
+#!/bin/sh
+# verifying-name-chaining - PKITS Test 4.3 -*- sh -*-
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+. ${srcdir:-.}/common.sh || exit 2
+
+section=4.3
+description="Verifying Name Chaining"
+info "Running $description tests"
+
+
+
+
+
+
+final_result
diff --git a/tests/pkits/verifying-paths-self-issued b/tests/pkits/verifying-paths-self-issued
new file mode 100755
index 0000000..443d7ad
--- /dev/null
+++ b/tests/pkits/verifying-paths-self-issued
@@ -0,0 +1,31 @@
+#!/bin/sh
+# verifying-paths-self-issued - PKITS Test 4.5 -*- sh -*-
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+. ${srcdir:-.}/common.sh || exit 2
+
+section=4.5
+description="Verifying Paths with Self-Issued Certificates"
+info "Running $description tests"
+
+
+
+
+
+
+final_result
diff --git a/tests/run-tests.scm b/tests/run-tests.scm
new file mode 100644
index 0000000..d3ebba0
--- /dev/null
+++ b/tests/run-tests.scm
@@ -0,0 +1,44 @@
+#!/usr/bin/env gpgscm
+
+;; Copyright (C) 2017 g10 Code GmbH
+;;
+;; This file is part of GnuPG.
+;;
+;; GnuPG is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GnuPG is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+(info "Running all tests...")
+
+(define (load-tests-with-log . path)
+ (map (lambda (test)
+ (test:::set! 'log-file-name
+ (apply path-join `(,@path
+ ,(string-append (basename test::name)
+ ".log")))))
+ (apply load-tests path)))
+
+(let ((prefix (flag "--prefix" *args*))
+ (all-tests (append
+ (load-tests-with-log "common")
+ (load-tests-with-log "g10")
+ (load-tests-with-log "g13")
+ (load-tests-with-log "agent")
+ (load-tests-with-log "tests" "openpgp")
+ (load-tests-with-log "tests" "migrations")
+ (load-tests-with-log "tests" "gpgsm")
+ (load-tests-with-log "tests" "gpgme"))))
+ (run-tests (if prefix
+ (filter
+ (lambda (t) (string-prefix? t::name (apply path-join prefix)))
+ all-tests)
+ all-tests)))
diff --git a/tests/runtest b/tests/runtest
new file mode 100755
index 0000000..5c832bd
--- /dev/null
+++ b/tests/runtest
@@ -0,0 +1,3 @@
+#!/bin/sh
+[ -x "$1" ] && exec $1 $2
+exec ./asschk --no-echo -DGPGSM=${GPGSM} <"$1"
diff --git a/tests/samplekeys/32100C27173EF6E9C4E9A25D3D69F86D37A4F939.key b/tests/samplekeys/32100C27173EF6E9C4E9A25D3D69F86D37A4F939.key
new file mode 100644
index 0000000..cf0535f
--- /dev/null
+++ b/tests/samplekeys/32100C27173EF6E9C4E9A25D3D69F86D37A4F939.key
@@ -0,0 +1,18 @@
+(private-key
+ (oid.1.2.840.113549.1.1.1
+ (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)
+ (e #010001#)
+ (d #046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B117D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BDC543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781#)
+ (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)
+ (q #00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f935a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361#)
+ (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891eebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)
+ )
+)
+
+
+
+
+
+
+
+
diff --git a/tests/samplekeys/68A638998DFABAC510EA645CE34F9686B2EDF7EA.key b/tests/samplekeys/68A638998DFABAC510EA645CE34F9686B2EDF7EA.key
new file mode 100644
index 0000000..8236349
--- /dev/null
+++ b/tests/samplekeys/68A638998DFABAC510EA645CE34F9686B2EDF7EA.key
@@ -0,0 +1,10 @@
+(private-key
+ (rsa
+ (n #0093687D92A7BCD1E6FC11263B50657A8FA4B9CEE3F90E23384D62778CA1B6CBE0F60B20354A5F74899EB3C8DDF3081D32475C71869BB0C5DAF0051A2F44596E7406F1DCC7B29D88735E49341F09F4DFCAB5A08B76614C37220CF7E2CDB8A38E79644F3A250FFAE5D0BBA6917C67523D2812FDE8D3BEA9947F6A55402B1600C12F#)
+ (e #010001#)
+ (d #11BAAE926B54482C04EDE1C59E877B5F382114F8D1BAAE926B54482C04EDE1C59E877B5F382114F8D1BAAE926B54482C04EDE1C59E877B5F382114F8D1BAAE905D3988DFC39FEF462A0655AC906CBC12F6D322795D3988DFC39FEF462A0655AC906CBC12F6D322795D3988DFC39FEF462A0655AC906CBC12F6D322795D3983C1#)
+ (p "\x00BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBA")
+ (q "\x00BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB")
+ (u #00B28879D8EEE03F5546A5BBAD0C2213728879D8EEE03F5546A5BBAD0C2213728879D8EEE03F5546A5BBAD0C2213728879D8EEE03F5546A5BBAD0C221372887A30#)
+ )
+ )
diff --git a/tests/samplekeys/cert_g10code_pete1.pem b/tests/samplekeys/cert_g10code_pete1.pem
new file mode 100644
index 0000000..c6f778a
--- /dev/null
+++ b/tests/samplekeys/cert_g10code_pete1.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIID7jCCA1egAwIBAgIBADANBgkqhkiG9w0BAQQFADCBsTELMAkGA1UEBhMCREUx
+DDAKBgNVBAgTA05SVzETMBEGA1UEBxQKRPxzc2VsZG9yZjEWMBQGA1UEChMNZzEw
+IENvZGUgR21iSDEbMBkGA1UECxMSS2VyY2tob2ZmcyBUZXN0bGFiMRYwFAYDVQQD
+Ew1QZXRlciBQYW50aGVyMTIwMAYJKoZIhvcNAQkBFiNwZXRlci5wYW50aGVyQGtl
+cmNraG9mZnMuZzEwY29kZS5kZTAeFw0wMjA0MTIxNjU4MzFaFw0wMzA0MTIxNjU4
+MzFaMIGxMQswCQYDVQQGEwJERTEMMAoGA1UECBMDTlJXMRMwEQYDVQQHFApE/HNz
+ZWxkb3JmMRYwFAYDVQQKEw1nMTAgQ29kZSBHbWJIMRswGQYDVQQLExJLZXJja2hv
+ZmZzIFRlc3RsYWIxFjAUBgNVBAMTDVBldGVyIFBhbnRoZXIxMjAwBgkqhkiG9w0B
+CQEWI3BldGVyLnBhbnRoZXJAa2VyY2tob2Zmcy5nMTBjb2RlLmRlMIGfMA0GCSqG
+SIb3DQEBAQUAA4GNADCBiQKBgQC/UYKEu+IZgvoUwbBaKT96SDsgnsOLkC7TWuP+
+td9qyjF+tQCSUdTqRDYyP44hLH24v4h9KsVxwl5iuncJCdNmpTHL4ika+3v7arGU
+DmGEHZOC3mHMzD+/dfqotse7C37AEMWSXguh4x2vmSESG9wnAxCgLl78j+RIuKUE
+RVK55wIDAQABo4IBEjCCAQ4wHQYDVR0OBBYEFDhJ93SfqHOecsryvYN01++o7qh/
+MIHeBgNVHSMEgdYwgdOAFDhJ93SfqHOecsryvYN01++o7qh/oYG3pIG0MIGxMQsw
+CQYDVQQGEwJERTEMMAoGA1UECBMDTlJXMRMwEQYDVQQHFApE/HNzZWxkb3JmMRYw
+FAYDVQQKEw1nMTAgQ29kZSBHbWJIMRswGQYDVQQLExJLZXJja2hvZmZzIFRlc3Rs
+YWIxFjAUBgNVBAMTDVBldGVyIFBhbnRoZXIxMjAwBgkqhkiG9w0BCQEWI3BldGVy
+LnBhbnRoZXJAa2VyY2tob2Zmcy5nMTBjb2RlLmRlggEAMAwGA1UdEwQFMAMBAf8w
+DQYJKoZIhvcNAQEEBQADgYEADoBAUnaZIjp+T60s1at/tLa03TfYT8DdTQz+p/UF
+MFGPz9CTqsoN7NLFoXyq+RN9FipsGEKLMif7e/buRqlcir+ntxqQFdy6EYfxfu4n
+Dys8JxnhjcEqXSz+uPUE8jiGho5Tkveo+hurDKZ54CVTeJtvKrWpA6YkuhmL/zRz
+T7Y=
+-----END CERTIFICATE-----
diff --git a/tests/samplekeys/cert_g10code_test1.pem b/tests/samplekeys/cert_g10code_test1.pem
new file mode 100644
index 0000000..61d1f98
--- /dev/null
+++ b/tests/samplekeys/cert_g10code_test1.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDFTCCAn6gAwIBAgIBADANBgkqhkiG9w0BAQQFADBrMQswCQYDVQQGEwJERTET
+MBEGA1UEBxQKRPxzc2VsZG9yZjEWMBQGA1UEChMNZzEwIENvZGUgR21iSDEZMBcG
+A1UECxMQQWVneXB0ZW4gUHJvamVjdDEUMBIGA1UEAxMLdGVzdCBjZXJ0IDEwHhcN
+MDExMjAzMDkzNjM4WhcNMDIxMjAzMDkzNjM4WjBrMQswCQYDVQQGEwJERTETMBEG
+A1UEBxQKRPxzc2VsZG9yZjEWMBQGA1UEChMNZzEwIENvZGUgR21iSDEZMBcGA1UE
+CxMQQWVneXB0ZW4gUHJvamVjdDEUMBIGA1UEAxMLdGVzdCBjZXJ0IDEwgZ8wDQYJ
+KoZIhvcNAQEBBQADgY0AMIGJAoGBAODOlvkLbJ4C85Ir6tqT/lCoderGvMGLuanP
+LoSWXKotH/laf1QkZcbAwZ0nbkUmzgSIaKepFP00PMOofddCkf/FZVBtW7sly6xq
+Di3R+LyqsNSinC83yVDzY0hL8mn3iRRARkuveYJ+A6NucLgUk47r3GPpZCR7513F
+iwFLfqJRAgMBAAGjgcgwgcUwHQYDVR0OBBYEFDM3jRKRwFRxgzhfCGW/qUv5jjTz
+MIGVBgNVHSMEgY0wgYqAFDM3jRKRwFRxgzhfCGW/qUv5jjTzoW+kbTBrMQswCQYD
+VQQGEwJERTETMBEGA1UEBxQKRPxzc2VsZG9yZjEWMBQGA1UEChMNZzEwIENvZGUg
+R21iSDEZMBcGA1UECxMQQWVneXB0ZW4gUHJvamVjdDEUMBIGA1UEAxMLdGVzdCBj
+ZXJ0IDGCAQAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBshwQeijio
+2hsXZxZEIFoNldDpdxcbWUws5utNJ7hqxQr74fn2cL9rH7AycNWtZnyCTAk7Uqwc
+bH3z6CNoJH6U/k//ITk7w8PtM6nw6JhlXLD+C65Bifip6id2JtRQwl4kJ/tPpx+/
+42Muki3yVFN+BEGFPpI6hdJmh1Hz81k8GQ==
+-----END CERTIFICATE-----
diff --git a/tests/samplekeys/cert_g10code_theo1.pem b/tests/samplekeys/cert_g10code_theo1.pem
new file mode 100644
index 0000000..a7685c4
--- /dev/null
+++ b/tests/samplekeys/cert_g10code_theo1.pem
@@ -0,0 +1,40 @@
+
+ <GnupgKeyblock>
+ <mainkey>
+ <keyid></keyid>
+ <fpr>E76B5D4BA2CF0B05BBBE425CDBF4E9DC4904941D</fpr>
+ <algo>0</algo>
+ <len>1024</len>
+ <created>1017250241</created>
+ <expire>1048786241</expire>
+ </mainkey>
+ <userid>
+ <raw>1.2.840.113549.1.9.1=#7468656F62616C642E7469676572406B6572636B686F6666732E673130636F64652E6465,CN=Theobald Tiger,OU=Kerckhoffs Testlab,O=g10 Code GmbH,L=Düsseldorf,ST=NRW,C=de</raw>
+ </userid>
+ </GnupgKeyblock>
+
+
+-----BEGIN CERTIFICATE-----
+MIID9DCCA12gAwIBAgIBADANBgkqhkiG9w0BAQQFADCBszELMAkGA1UEBhMCZGUx
+DDAKBgNVBAgTA05SVzETMBEGA1UEBxQKRPxzc2VsZG9yZjEWMBQGA1UEChMNZzEw
+IENvZGUgR21iSDEbMBkGA1UECxMSS2VyY2tob2ZmcyBUZXN0bGFiMRcwFQYDVQQD
+Ew5UaGVvYmFsZCBUaWdlcjEzMDEGCSqGSIb3DQEJARYkdGhlb2JhbGQudGlnZXJA
+a2VyY2tob2Zmcy5nMTBjb2RlLmRlMB4XDTAyMDMyNzE3MzA0MVoXDTAzMDMyNzE3
+MzA0MVowgbMxCzAJBgNVBAYTAmRlMQwwCgYDVQQIEwNOUlcxEzARBgNVBAcUCkT8
+c3NlbGRvcmYxFjAUBgNVBAoTDWcxMCBDb2RlIEdtYkgxGzAZBgNVBAsTEktlcmNr
+aG9mZnMgVGVzdGxhYjEXMBUGA1UEAxMOVGhlb2JhbGQgVGlnZXIxMzAxBgkqhkiG
+9w0BCQEWJHRoZW9iYWxkLnRpZ2VyQGtlcmNraG9mZnMuZzEwY29kZS5kZTCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2N+6T7awrnWhg1g+HIE8TGn3e8OOkqmE
+v2k7uazL2aGUIk2Omg+2Jjq2dovotiSAjoVQFtJ+Ahk4aiGFA4Zdp34ZzijpXhD+
++xbFt1Vz/zBWlExpN9A5m2XPAbcW5rTMcl9O6jXKgu4sLDXOGOVCSOIpaQGwB3g3
+ti/p7J4lvFcCAwEAAaOCARQwggEQMB0GA1UdDgQWBBQTVJsLsvwdrA5XJMZyCECy
+gFdHGzCB4AYDVR0jBIHYMIHVgBQTVJsLsvwdrA5XJMZyCECygFdHG6GBuaSBtjCB
+szELMAkGA1UEBhMCZGUxDDAKBgNVBAgTA05SVzETMBEGA1UEBxQKRPxzc2VsZG9y
+ZjEWMBQGA1UEChMNZzEwIENvZGUgR21iSDEbMBkGA1UECxMSS2VyY2tob2ZmcyBU
+ZXN0bGFiMRcwFQYDVQQDEw5UaGVvYmFsZCBUaWdlcjEzMDEGCSqGSIb3DQEJARYk
+dGhlb2JhbGQudGlnZXJAa2VyY2tob2Zmcy5nMTBjb2RlLmRlggEAMAwGA1UdEwQF
+MAMBAf8wDQYJKoZIhvcNAQEEBQADgYEASILHzi6O8Gf4Xd98FFtln3FGLhlHlxKV
+xuO4Qn+qcBN7dFfQE3B/WKRR5jC8NTZHgGzAzcVv/ha2AAVs/zbSxE6lU04OOSJv
+qm9lo6lsm5P+C/NH/hSdlUfSoKbmt5ZAPYpOhHvmPQpLi4Iv4hjeFqoCN5OVXOXN
+OSgvBzegSSA=
+-----END CERTIFICATE-----
diff --git a/tests/samplekeys/steed-self-signing-nonthority.pem b/tests/samplekeys/steed-self-signing-nonthority.pem
new file mode 100644
index 0000000..c6a9c54
--- /dev/null
+++ b/tests/samplekeys/steed-self-signing-nonthority.pem
@@ -0,0 +1,54 @@
+
+ ID: 0x72B0BD08
+ S/N: 01
+ Issuer: CN=The STEED Self-Signing Nonthority
+ Subject: CN=The STEED Self-Signing Nonthority
+ sha1_fpr: E6:99:39:A2:5F:5D:93:F2:06:71:5D:C9:FC:1A:25:DC:72:B0:BD:08
+ md5_fpr: C9:83:C8:13:91:53:5A:C2:9A:BA:AF:0E:9C:AF:93:0E
+ certid: BA9A5990A0E94A627D08D4D06FD15EC561FD15E8.01
+ keygrip: 68A638998DFABAC510EA645CE34F9686B2EDF7EA
+ notBefore: 2011-11-11 00:00:00
+ notAfter: 2106-02-06 00:00:00
+ hashAlgo: 1.2.840.113549.1.1.5 (sha1WithRSAEncryption)
+ keyType: 1024 bit RSA
+ subjKeyId: 68A638998DFABAC510EA645CE34F9686B2EDF7EA
+ authKeyId: [none]
+ keyUsage: certSign crlSign
+ extKeyUsage: [none]
+ policies: [none]
+ chainLength: 1
+ crlDP: [none]
+ authInfo: [none]
+ subjInfo: [none]
+ extn: 1.3.6.1.4.1.11591.2.2.2 (wellKnownPrivateKey) [3 octets]
+
+
+-----BEGIN CERTIFICATE-----
+MIICKDCCAZGgAwIBAgIBATANBgkqhkiG9w0BAQUFADAsMSowKAYDVQQDEyFUaGUg
+U1RFRUQgU2VsZi1TaWduaW5nIE5vbnRob3JpdHkwIBcNMTExMTExMDAwMDAwWhgP
+MjEwNjAyMDYwMDAwMDBaMCwxKjAoBgNVBAMTIVRoZSBTVEVFRCBTZWxmLVNpZ25p
+bmcgTm9udGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAk2h9kqe8
+0eb8ESY7UGV6j6S5zuP5DiM4TWJ3jKG2y+D2CyA1Sl90iZ6zyN3zCB0yR1xxhpuw
+xdrwBRovRFludAbx3MeynYhzXkk0Hwn038q1oIt2YUw3Igz34s24o455ZE86JQ/6
+5dC7ppF8Z1I9KBL96NO+qZR/alVAKxYAwS8CAwEAAaNYMFYwEgYDVR0TAQH/BAgw
+BgEB/wIBATARBgorBgEEAdpHAgICBAMBAf8wHQYDVR0OBBYEFGimOJmN+rrFEOpk
+XONPloay7ffqMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOBgQB3JwUn
+AbOdGv5ErojNSSP+yGZIy5av4wnkzK840Uj3jY6A5cuHroZGOD60hqLV2Hy0npox
+zte4phWEKWmZiXd8SCmd3MFNgZSieiixye0qxSmuqYft2j6NhEXD5xc/iTTjFT42
+SjGPLKAICuMBuGPnoozOEVlgqwaDqKOUph5sqw==
+-----END CERTIFICATE-----
+
+Created using these parameters:
+
+ Key-Type: RSA
+ Key-Length: 1024
+ Key-Grip: 68A638998DFABAC510EA645CE34F9686B2EDF7EA
+ Key-Usage: cert
+ Serial: 1
+ Name-DN: CN=The STEED Self-Signing Nonthority
+ Not-Before: 2011-11-11
+ Not-After: 2106-02-06
+ Subject-Key-Id: 68A638998DFABAC510EA645CE34F9686B2EDF7EA
+ Extension: 2.5.29.19 c 30060101ff020101
+ Extension: 1.3.6.1.4.1.11591.2.2.2 n 0101ff
+ Signing-Key: 68A638998DFABAC510EA645CE34F9686B2EDF7EA
diff --git a/tests/sm-sign+verify b/tests/sm-sign+verify
new file mode 100644
index 0000000..1c3ae7d
--- /dev/null
+++ b/tests/sm-sign+verify
@@ -0,0 +1,73 @@
+# sm-sign+verify
+#
+# Creating a signature and verifying it
+# Requirements: a plain file "text-1.txt"
+
+srcdir = getenv srcdir
+plaintext = let $srcdir/text-1.txt
+
+in = openfile $plaintext
+out = createfile msg.sig
+in2 = openfile msg.sig
+out2 = createfile msg.unsig
+
+pipeserver $GPGSM
+send INPUT FD=$in
+expect-ok
+send OUTPUT FD=$out
+expect-ok
+send SIGN
+expect-ok
+
+send RESET
+expect-ok
+send INPUT FD=$in2
+expect-ok
+send OUTPUT FD=$out2
+expect-ok
+goodsig = count-status GOODSIG
+trusted = count-status TRUST_FULLY
+send VERIFY
+expect-ok
+echo goodsig=$goodsig trusted=$trusted
+fail-if !$goodsig
+fail-if !$trusted
+send BYE
+expect-ok
+
+# Unset variables so that the files get closed.
+in =
+out =
+in2 =
+out2=
+
+cmpfiles $plaintext msg.unsig
+fail-if !$?
+
+# Lets check it again with a new server instance, this time we keep
+# the server running to check whether the entire message has been
+# output after the VERIFY.
+in = openfile msg.sig
+out = createfile msg.unsig
+pipeserver $GPGSM
+send INPUT FD=$in
+expect-ok
+send OUTPUT FD=$out
+expect-ok
+goodsig = count-status GOODSIG
+trusted = count-status TRUST_FULLY
+send VERIFY
+expect-ok
+echo goodsig=$goodsig trusted=$trusted
+fail-if !$goodsig
+fail-if !$trusted
+
+cmpfiles $plaintext msg.unsig
+fail-if !$?
+
+send BYE
+expect-ok
+
+
+quit
+
diff --git a/tests/sm-verify b/tests/sm-verify
new file mode 100644
index 0000000..b06dc16
--- /dev/null
+++ b/tests/sm-verify
@@ -0,0 +1,114 @@
+# sm-verify
+#
+# Verify a few distributed signatures.
+# Requirements:
+#
+
+srcdir = getenv srcdir
+
+# Check an opaque signature
+sig = openfile $srcdir/text-1.osig.pem
+out = createfile msg.unsig
+pipeserver $GPGSM
+send INPUT FD=$sig
+expect-ok
+send OUTPUT FD=$out
+expect-ok
+badsig = count-status BADSIG
+goodsig = count-status GOODSIG
+trusted = count-status TRUST_FULLY
+send VERIFY
+expect-ok
+echo badsig=$badsig goodsig=$goodsig trusted=$trusted
+fail-if $badsig
+fail-if !$goodsig
+fail-if !$trusted
+send BYE
+expect-ok
+
+sig =
+out =
+cmpfiles $srcdir/text-1.txt msg.unsig
+fail-if !$?
+
+# Check a detached signature.
+sig = openfile $srcdir/text-1.dsig.pem
+plain = openfile $srcdir/text-1.txt
+pipeserver $GPGSM
+send INPUT FD=$sig
+expect-ok
+send MESSAGE FD=$plain
+expect-ok
+badsig = count-status BADSIG
+goodsig = count-status GOODSIG
+trusted = count-status TRUST_FULLY
+send VERIFY
+expect-ok
+echo badsig=$badsig goodsig=$goodsig trusted=$trusted
+fail-if $badsig
+fail-if !$goodsig
+fail-if !$trusted
+send BYE
+expect-ok
+
+# Check a tampered opaque message
+sig = openfile $srcdir/text-1.osig-bad.pem
+out = createfile msg.unsig
+
+pipeserver $GPGSM
+send INPUT FD=$sig
+expect-ok
+send OUTPUT FD=$out
+expect-ok
+badsig = count-status BADSIG
+goodsig = count-status GOODSIG
+trusted = count-status TRUST_FULLY
+send VERIFY
+expect-ok
+echo badsig=$badsig goodsig=$goodsig trusted=$trusted
+fail-if $goodsig
+fail-if !$badsig
+fail-if $trusted
+send BYE
+expect-ok
+
+# Check another opaque signature but without asking for the output.
+sig = openfile $srcdir/text-2.osig.pem
+
+pipeserver $GPGSM
+send INPUT FD=$sig
+expect-ok
+badsig = count-status BADSIG
+goodsig = count-status GOODSIG
+trusted = count-status TRUST_FULLY
+send VERIFY
+expect-ok
+echo badsig=$badsig goodsig=$goodsig trusted=$trusted
+fail-if $badsig
+fail-if !$goodsig
+fail-if !$trusted
+send BYE
+expect-ok
+
+# We als have tampered version.
+sig = openfile $srcdir/text-2.osig-bad.pem
+
+pipeserver $GPGSM
+send INPUT FD=$sig
+expect-ok
+badsig = count-status BADSIG
+goodsig = count-status GOODSIG
+trusted = count-status TRUST_FULLY
+send VERIFY
+expect-ok
+echo badsig=$badsig goodsig=$goodsig trusted=$trusted
+fail-if $goodsig
+fail-if !$badsig
+fail-if $trusted
+send BYE
+expect-ok
+
+
+quit
+
+
diff --git a/tests/text-1.dsig.pem b/tests/text-1.dsig.pem
new file mode 100644
index 0000000..a031ec2
--- /dev/null
+++ b/tests/text-1.dsig.pem
@@ -0,0 +1,27 @@
+-----BEGIN SIGNED MESSAGE-----
+MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAA
+oIIDGTCCAxUwggJ+oAMCAQICAQAwDQYJKoZIhvcNAQEEBQAwazELMAkGA1UEBhMC
+REUxEzARBgNVBAcUCkT8c3NlbGRvcmYxFjAUBgNVBAoTDWcxMCBDb2RlIEdtYkgx
+GTAXBgNVBAsTEEFlZ3lwdGVuIFByb2plY3QxFDASBgNVBAMTC3Rlc3QgY2VydCAx
+MB4XDTAxMTIwMzA5MzYzOFoXDTAyMTIwMzA5MzYzOFowazELMAkGA1UEBhMCREUx
+EzARBgNVBAcUCkT8c3NlbGRvcmYxFjAUBgNVBAoTDWcxMCBDb2RlIEdtYkgxGTAX
+BgNVBAsTEEFlZ3lwdGVuIFByb2plY3QxFDASBgNVBAMTC3Rlc3QgY2VydCAxMIGf
+MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgzpb5C2yeAvOSK+rak/5QqHXqxrzB
+i7mpzy6EllyqLR/5Wn9UJGXGwMGdJ25FJs4EiGinqRT9NDzDqH3XQpH/xWVQbVu7
+Jcusag4t0fi8qrDUopwvN8lQ82NIS/Jp94kUQEZLr3mCfgOjbnC4FJOO69xj6WQk
+e+ddxYsBS36iUQIDAQABo4HIMIHFMB0GA1UdDgQWBBQzN40SkcBUcYM4Xwhlv6lL
++Y408zCBlQYDVR0jBIGNMIGKgBQzN40SkcBUcYM4Xwhlv6lL+Y4086FvpG0wazEL
+MAkGA1UEBhMCREUxEzARBgNVBAcUCkT8c3NlbGRvcmYxFjAUBgNVBAoTDWcxMCBD
+b2RlIEdtYkgxGTAXBgNVBAsTEEFlZ3lwdGVuIFByb2plY3QxFDASBgNVBAMTC3Rl
+c3QgY2VydCAxggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAbIcE
+Hoo4qNobF2cWRCBaDZXQ6XcXG1lMLObrTSe4asUK++H59nC/ax+wMnDVrWZ8gkwJ
+O1KsHGx98+gjaCR+lP5P/yE5O8PD7TOp8OiYZVyw/guuQYn4qeondibUUMJeJCf7
+T6cfv+NjLpIt8lRTfgRBhT6SOoXSZodR8/NZPBkxggFXMIIBUwIBATBwMGsxCzAJ
+BgNVBAYTAkRFMRMwEQYDVQQHFApE/HNzZWxkb3JmMRYwFAYDVQQKEw1nMTAgQ29k
+ZSBHbWJIMRkwFwYDVQQLExBBZWd5cHRlbiBQcm9qZWN0MRQwEgYDVQQDEwt0ZXN0
+IGNlcnQgMQIBADAHBgUrDgMCGqBDMBwGCSqGSIb3DQEJBTEPFw0wMjA4MDgxMjIy
+NTRaMCMGCSqGSIb3DQEJBDEWBBR5MsAm+0wJAVQl3AAGYmnpxA4XLjALBgkqhkiG
+9w0BAQEEgYAZpBbucgorq56kl2rokCV1EAZcKgylfpEkqSz4RU6qNid+0NtjSAxi
+5164wjMLG71U9qSBX4XDdDQPHpH+PPF/8021kne2kPfeP68NiXK8CagdIqlnuJEj
+K934mVre7AIjrXqoob1ipUtCWeK+2uHXsUjtUn3u1Y3eWVZ6+1hDTAAAAAAAAA==
+-----END SIGNED MESSAGE-----
diff --git a/tests/text-1.osig-bad.pem b/tests/text-1.osig-bad.pem
new file mode 100644
index 0000000..0b5f4a4
--- /dev/null
+++ b/tests/text-1.osig-bad.pem
@@ -0,0 +1,45 @@
+The text in this message has been tampered.
+
+-----BEGIN SIGNED MESSAGE-----
+MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCAJIAEggPh
+SGlnaCBQcmllc3Q6CUFybWFtZW50cyBDaGFwdGVyIE9uZSwgdmVyc2VzIG5pbmUgdGhyb3Vn
+aCB0d2VudHktc2V2ZW46CkJyby4gTWF5bmFyZDoJQW5kIFNhaW50IEF0dGlsYSByYWlzZWQg
+dGhlIEhvbHkgSGFuZCBHcmVuYWRlIHVwIG9uIGhpZ2gKCXNheWluZywgIk9oIExvcmQsIEJs
+ZXNzIHVzIHRoaXMgSG9seSBIYW5kIEdyZW5hZGUsIGFuZCB3aXRoIGl0CglzbWFzaCBvdXIg
+ZW5lbWllcyB0byB0aW55IGJpdHMuIiAgQW5kIHRoZSBMb3JkIGRpZCBncmluLCBhbmQgdGhl
+CglwZW9wbGUgZGlkIGZlYXN0IHVwb24gdGhlIGxhbWJzLCBhbmQgc3RvYXRzLCBhbmQgb3Jh
+bmd1dGFucywgYW5kCglicmVha2Zhc3QgY2VyZWFscywgYW5kIGxpbWEgYmVhbi0KSGlnaCBQ
+cmllc3Q6CVNraXAgYSBiaXQsIHNpc3Rlci4gCkJyby4gTWF5bmFyZDoJQW5kIHRoZW4gdGhl
+IExvcmQgc3Bha2UsIHNheWluZzogIkZpcnN0LCBzaGFsdCB0aG91IHRha2UKCW91dCB0aGUg
+aG9seSBwaW4uICBUaGVuIHNoYWx0IHRob3UgY291bnQgdG8gdGhyZWUuICBObyBtb3JlLCBu
+byBsZXNzLgoJKlRocmVlKiBzaGFsbCBiZSB0aGUgbnVtYmVyIG9mIHRoZSBjb3VudGluZywg
+YW5kIHRoZSBudW1iZXIgb2YgdGhlCgljb3VudGluZyBzaGFsbCBiZSB0aHJlZS4gICpGb3Vy
+KiBzaGFsdCB0aG91IG5vdCBjb3VudCwgYW5kIG5laXRoZXIKCWNvdW50IHRob3UgdHdvLCBl
+eGNlcHRpbmcgdGhhdCB0aG91IHRoZW4gZ29lc3Qgb24gdG8gdGhyZWUuICBGaXZlIGlzCglS
+SUdIVCBPVVQuICBPbmNlIHRoZSBudW1iZXIgdGhyZWUsIGJlaW5nIHRoZSB0aGlyZCBudW1i
+ZXIgYmUgcmVhY2hlZCwKCXRoZW4gbG9iYmVzdCB0aG91IHRoeSBIb2x5IEhhbmQgR3JlbmFk
+ZSB0b3dhcmRzIHRoeSBmb2UsIHdobywgYmVpbmcKCW5hdWdodHkgaW4gbXkgc2lnaHQsIHNo
+YWxsIHNudWZmIGl0LiAgQW1lbi4KQWxsOglBbWVuLgoJCS0tIE1vbnR5IFB5dGhvbiwgIlRo
+ZSBIb2x5IEhhbmQgR3JlbmFkZSIKAAAAAAAAoIIDGTCCAxUwggJ+oAMCAQICAQAwDQYJKoZI
+hvcNAQEEBQAwazELMAkGA1UEBhMCREUxEzARBgNVBAcUCkT8c3NlbGRvcmYxFjAUBgNVBAoT
+DWcxMCBDb2RlIEdtYkgxGTAXBgNVBAsTEEFlZ3lwdGVuIFByb2plY3QxFDASBgNVBAMTC3Rl
+c3QgY2VydCAxMB4XDTAxMTIwMzA5MzYzOFoXDTAyMTIwMzA5MzYzOFowazELMAkGA1UEBhMC
+REUxEzARBgNVBAcUCkT8c3NlbGRvcmYxFjAUBgNVBAoTDWcxMCBDb2RlIEdtYkgxGTAXBgNV
+BAsTEEFlZ3lwdGVuIFByb2plY3QxFDASBgNVBAMTC3Rlc3QgY2VydCAxMIGfMA0GCSqGSIb3
+DQEBAQUAA4GNADCBiQKBgQDgzpb5C2yeAvOSK+rak/5QqHXqxrzBi7mpzy6EllyqLR/5Wn9U
+JGXGwMGdJ25FJs4EiGinqRT9NDzDqH3XQpH/xWVQbVu7Jcusag4t0fi8qrDUopwvN8lQ82NI
+S/Jp94kUQEZLr3mCfgOjbnC4FJOO69xj6WQke+ddxYsBS36iUQIDAQABo4HIMIHFMB0GA1Ud
+DgQWBBQzN40SkcBUcYM4Xwhlv6lL+Y408zCBlQYDVR0jBIGNMIGKgBQzN40SkcBUcYM4Xwhl
+v6lL+Y4086FvpG0wazELMAkGA1UEBhMCREUxEzARBgNVBAcUCkT8c3NlbGRvcmYxFjAUBgNV
+BAoTDWcxMCBDb2RlIEdtYkgxGTAXBgNVBAsTEEFlZ3lwdGVuIFByb2plY3QxFDASBgNVBAMT
+C3Rlc3QgY2VydCAxggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAbIcEHoo4
+qNobF2cWRCBaDZXQ6XcXG1lMLObrTSe4asUK++H59nC/ax+wMnDVrWZ8gkwJO1KsHGx98+gj
+aCR+lP5P/yE5O8PD7TOp8OiYZVyw/guuQYn4qeondibUUMJeJCf7T6cfv+NjLpIt8lRTfgRB
+hT6SOoXSZodR8/NZPBkxggFXMIIBUwIBATBwMGsxCzAJBgNVBAYTAkRFMRMwEQYDVQQHFApE
+/HNzZWxkb3JmMRYwFAYDVQQKEw1nMTAgQ29kZSBHbWJIMRkwFwYDVQQLExBBZWd5cHRlbiBQ
+cm9qZWN0MRQwEgYDVQQDEwt0ZXN0IGNlcnQgMQIBADAHBgUrDgMCGqBDMBwGCSqGSIb3DQEJ
+BTEPFw0wMjA4MDgxMjIyNDZaMCMGCSqGSIb3DQEJBDEWBBR5MsAm+0wJAVQl3AAGYmnpxA4X
+LjALBgkqhkiG9w0BAQEEgYC+7rFtegP8v+Z5yI4CH/0Y4RK48DM1oFMSz4xySpERFTk9p5RP
+BDhOqaaACVKUdmNW6xYJAFo53tQxbBTZ12woctFLbLm9rs/F6Tz2JIA9GxpXInkKYdvkaVHb
+pvEQgeoezFc4fd4yB87kgq4zZTViFcCJ3OvjboCu9ltIeIn73AAAAAAAAA==
+-----END SIGNED MESSAGE-----
diff --git a/tests/text-1.osig.pem b/tests/text-1.osig.pem
new file mode 100644
index 0000000..7317350
--- /dev/null
+++ b/tests/text-1.osig.pem
@@ -0,0 +1,48 @@
+-----BEGIN SIGNED MESSAGE-----
+MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCA
+JIAEggPhSGlnaCBQcmllc3Q6CUFybWFtZW50cyBDaGFwdGVyIE9uZSwgdmVyc2Vz
+IG5pbmUgdGhyb3VnaCB0d2VudHktc2V2ZW46CkJyby4gTWF5bmFyZDoJQW5kIFNh
+aW50IEF0dGlsYSByYWlzZWQgdGhlIEhvbHkgSGFuZCBHcmVuYWRlIHVwIG9uIGhp
+Z2gKCXNheWluZywgIk9oIExvcmQsIEJsZXNzIHVzIHRoaXMgSG9seSBIYW5kIEdy
+ZW5hZGUsIGFuZCB3aXRoIGl0CglzbWFzaCBvdXIgZW5lbWllcyB0byB0aW55IGJp
+dHMuIiAgQW5kIHRoZSBMb3JkIGRpZCBncmluLCBhbmQgdGhlCglwZW9wbGUgZGlk
+IGZlYXN0IHVwb24gdGhlIGxhbWJzLCBhbmQgc3RvYXRzLCBhbmQgb3Jhbmd1dGFu
+cywgYW5kCglicmVha2Zhc3QgY2VyZWFscywgYW5kIGxpbWEgYmVhbi0KSGlnaCBQ
+cmllc3Q6CVNraXAgYSBiaXQsIGJyb3RoZXIuCkJyby4gTWF5bmFyZDoJQW5kIHRo
+ZW4gdGhlIExvcmQgc3Bha2UsIHNheWluZzogIkZpcnN0LCBzaGFsdCB0aG91IHRh
+a2UKCW91dCB0aGUgaG9seSBwaW4uICBUaGVuIHNoYWx0IHRob3UgY291bnQgdG8g
+dGhyZWUuICBObyBtb3JlLCBubyBsZXNzLgoJKlRocmVlKiBzaGFsbCBiZSB0aGUg
+bnVtYmVyIG9mIHRoZSBjb3VudGluZywgYW5kIHRoZSBudW1iZXIgb2YgdGhlCglj
+b3VudGluZyBzaGFsbCBiZSB0aHJlZS4gICpGb3VyKiBzaGFsdCB0aG91IG5vdCBj
+b3VudCwgYW5kIG5laXRoZXIKCWNvdW50IHRob3UgdHdvLCBleGNlcHRpbmcgdGhh
+dCB0aG91IHRoZW4gZ29lc3Qgb24gdG8gdGhyZWUuICBGaXZlIGlzCglSSUdIVCBP
+VVQuICBPbmNlIHRoZSBudW1iZXIgdGhyZWUsIGJlaW5nIHRoZSB0aGlyZCBudW1i
+ZXIgYmUgcmVhY2hlZCwKCXRoZW4gbG9iYmVzdCB0aG91IHRoeSBIb2x5IEhhbmQg
+R3JlbmFkZSB0b3dhcmRzIHRoeSBmb2UsIHdobywgYmVpbmcKCW5hdWdodHkgaW4g
+bXkgc2lnaHQsIHNoYWxsIHNudWZmIGl0LiAgQW1lbi4KQWxsOglBbWVuLgoJCS0t
+IE1vbnR5IFB5dGhvbiwgIlRoZSBIb2x5IEhhbmQgR3JlbmFkZSIKAAAAAAAAoIID
+GTCCAxUwggJ+oAMCAQICAQAwDQYJKoZIhvcNAQEEBQAwazELMAkGA1UEBhMCREUx
+EzARBgNVBAcUCkT8c3NlbGRvcmYxFjAUBgNVBAoTDWcxMCBDb2RlIEdtYkgxGTAX
+BgNVBAsTEEFlZ3lwdGVuIFByb2plY3QxFDASBgNVBAMTC3Rlc3QgY2VydCAxMB4X
+DTAxMTIwMzA5MzYzOFoXDTAyMTIwMzA5MzYzOFowazELMAkGA1UEBhMCREUxEzAR
+BgNVBAcUCkT8c3NlbGRvcmYxFjAUBgNVBAoTDWcxMCBDb2RlIEdtYkgxGTAXBgNV
+BAsTEEFlZ3lwdGVuIFByb2plY3QxFDASBgNVBAMTC3Rlc3QgY2VydCAxMIGfMA0G
+CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgzpb5C2yeAvOSK+rak/5QqHXqxrzBi7mp
+zy6EllyqLR/5Wn9UJGXGwMGdJ25FJs4EiGinqRT9NDzDqH3XQpH/xWVQbVu7Jcus
+ag4t0fi8qrDUopwvN8lQ82NIS/Jp94kUQEZLr3mCfgOjbnC4FJOO69xj6WQke+dd
+xYsBS36iUQIDAQABo4HIMIHFMB0GA1UdDgQWBBQzN40SkcBUcYM4Xwhlv6lL+Y40
+8zCBlQYDVR0jBIGNMIGKgBQzN40SkcBUcYM4Xwhlv6lL+Y4086FvpG0wazELMAkG
+A1UEBhMCREUxEzARBgNVBAcUCkT8c3NlbGRvcmYxFjAUBgNVBAoTDWcxMCBDb2Rl
+IEdtYkgxGTAXBgNVBAsTEEFlZ3lwdGVuIFByb2plY3QxFDASBgNVBAMTC3Rlc3Qg
+Y2VydCAxggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAbIcEHoo4
+qNobF2cWRCBaDZXQ6XcXG1lMLObrTSe4asUK++H59nC/ax+wMnDVrWZ8gkwJO1Ks
+HGx98+gjaCR+lP5P/yE5O8PD7TOp8OiYZVyw/guuQYn4qeondibUUMJeJCf7T6cf
+v+NjLpIt8lRTfgRBhT6SOoXSZodR8/NZPBkxggFXMIIBUwIBATBwMGsxCzAJBgNV
+BAYTAkRFMRMwEQYDVQQHFApE/HNzZWxkb3JmMRYwFAYDVQQKEw1nMTAgQ29kZSBH
+bWJIMRkwFwYDVQQLExBBZWd5cHRlbiBQcm9qZWN0MRQwEgYDVQQDEwt0ZXN0IGNl
+cnQgMQIBADAHBgUrDgMCGqBDMBwGCSqGSIb3DQEJBTEPFw0wMjA4MDgxMjIyNDZa
+MCMGCSqGSIb3DQEJBDEWBBR5MsAm+0wJAVQl3AAGYmnpxA4XLjALBgkqhkiG9w0B
+AQEEgYC+7rFtegP8v+Z5yI4CH/0Y4RK48DM1oFMSz4xySpERFTk9p5RPBDhOqaaA
+CVKUdmNW6xYJAFo53tQxbBTZ12woctFLbLm9rs/F6Tz2JIA9GxpXInkKYdvkaVHb
+pvEQgeoezFc4fd4yB87kgq4zZTViFcCJ3OvjboCu9ltIeIn73AAAAAAAAA==
+-----END SIGNED MESSAGE-----
diff --git a/tests/text-1.txt b/tests/text-1.txt
new file mode 100644
index 0000000..b14c1a2
--- /dev/null
+++ b/tests/text-1.txt
@@ -0,0 +1,17 @@
+High Priest: Armaments Chapter One, verses nine through twenty-seven:
+Bro. Maynard: And Saint Attila raised the Holy Hand Grenade up on high
+ saying, "Oh Lord, Bless us this Holy Hand Grenade, and with it
+ smash our enemies to tiny bits." And the Lord did grin, and the
+ people did feast upon the lambs, and stoats, and orangutans, and
+ breakfast cereals, and lima bean-
+High Priest: Skip a bit, brother.
+Bro. Maynard: And then the Lord spake, saying: "First, shalt thou take
+ out the holy pin. Then shalt thou count to three. No more, no less.
+ *Three* shall be the number of the counting, and the number of the
+ counting shall be three. *Four* shalt thou not count, and neither
+ count thou two, excepting that thou then goest on to three. Five is
+ RIGHT OUT. Once the number three, being the third number be reached,
+ then lobbest thou thy Holy Hand Grenade towards thy foe, who, being
+ naughty in my sight, shall snuff it. Amen.
+All: Amen.
+ -- Monty Python, "The Holy Hand Grenade"
diff --git a/tests/text-2.osig-bad.pem b/tests/text-2.osig-bad.pem
new file mode 100644
index 0000000..5558448
--- /dev/null
+++ b/tests/text-2.osig-bad.pem
@@ -0,0 +1,28 @@
+The signature time in this message has been tampered.
+
+-----BEGIN SIGNED MESSAGE-----
+MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCAJIAEU01p
+bGl0YXJ5IGludGVsbGlnZW5jZSBpcyBhIGNvbnRyYWRpY3Rpb24gaW4gdGVybXMuCiAgICAg
+ICAgICAgICAgICAtLSBHcm91Y2hvIE1hcngKAAAAAAAAoIIDGTCCAxUwggJ+oAMCAQICAQAw
+DQYJKoZIhvcNAQEEBQAwazELMAkGA1UEBhMCREUxEzARBgNVBAcUCkT8c3NlbGRvcmYxFjAU
+BgNVBAoTDWcxMCBDb2RlIEdtYkgxGTAXBgNVBAsTEEFlZ3lwdGVuIFByb2plY3QxFDASBgNV
+BAMTC3Rlc3QgY2VydCAxMB4XDTAxMTIwMzA5MzYzOFoXDTAyMTIwMzA5MzYzOFowazELMAkG
+A1UEBhMCREUxEzARBgNVBAcUCkT8c3NlbGRvcmYxFjAUBgNVBAoTDWcxMCBDb2RlIEdtYkgx
+GTAXBgNVBAsTEEFlZ3lwdGVuIFByb2plY3QxFDASBgNVBAMTC3Rlc3QgY2VydCAxMIGfMA0G
+CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgzpb5C2yeAvOSK+rak/5QqHXqxrzBi7mpzy6Ellyq
+LR/5Wn9UJGXGwMGdJ25FJs4EiGinqRT9NDzDqH3XQpH/xWVQbVu7Jcusag4t0fi8qrDUopwv
+N8lQ82NIS/Jp94kUQEZLr3mCfgOjbnC4FJOO69xj6WQke+ddxYsBS36iUQIDAQABo4HIMIHF
+MB0GA1UdDgQWBBQzN40SkcBUcYM4Xwhlv6lL+Y408zCBlQYDVR0jBIGNMIGKgBQzN40SkcBU
+cYM4Xwhlv6lL+Y4086FvpG0wazELMAkGA1UEBhMCREUxEzARBgNVBAcUCkT8c3NlbGRvcmYx
+FjAUBgNVBAoTDWcxMCBDb2RlIEdtYkgxGTAXBgNVBAsTEEFlZ3lwdGVuIFByb2plY3QxFDAS
+BgNVBAMTC3Rlc3QgY2VydCAxggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEA
+bIcEHoo4qNobF2cWRCBaDZXQ6XcXG1lMLObrTSe4asUK++H59nC/ax+wMnDVrWZ8gkwJO1Ks
+HGx98+gjaCR+lP5P/yE5O8PD7TOp8OiYZVyw/guuQYn4qeondibUUMJeJCf7T6cfv+NjLpIt
+8lRTfgRBhT6SOoXSZodR8/NZPBkxggFXMIIBUwIBATBwMGsxCzAJBgNVBAYTAkRFMRMwEQYD
+VQQHFApE/HNzZWxkb3JmMRYwFAYDVQQKEw1nMTAgQ29kZSBHbWJIMRkwFwYDVQQLExBBZWd5
+cHRlbiBQcm9qZWN0MRQwEgYDVQQDEwt0ZXN0IGNlcnQgMQIBADAHBgUrDgMCGqBDMBwGCSqG
+SIb3DQEJBTEPFw0wMjA4MDcxMjM4MjJaMCMGCSqGSIb3DQEJBDEWBBSzI9M4i+WJMTDoCeLu
+lJP7p1PCezALBgkqhkiG9w0BAQEEgYAqoJR3uJkChUhaH0EH3U5JpQApIhVEqedaKPT6BCPP
+WALFPzEa6YKzftA5e+Dap41UnB8nQ9rfwYty3hw5EulzV9iLnhGornQIgI6D5o7ymxyacsiY
+EarezxGXjuPMnyXcpTOgt+vz2k3qisjzxU32zpsOuK6U82PSHysX8rH9QgAAAAAAAA==
+-----END SIGNED MESSAGE-----
diff --git a/tests/text-2.osig.pem b/tests/text-2.osig.pem
new file mode 100644
index 0000000..57b5da9
--- /dev/null
+++ b/tests/text-2.osig.pem
@@ -0,0 +1,29 @@
+-----BEGIN SIGNED MESSAGE-----
+MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCA
+JIAEU01pbGl0YXJ5IGludGVsbGlnZW5jZSBpcyBhIGNvbnRyYWRpY3Rpb24gaW4g
+dGVybXMuCiAgICAgICAgICAgICAgICAtLSBHcm91Y2hvIE1hcngKAAAAAAAAoIID
+GTCCAxUwggJ+oAMCAQICAQAwDQYJKoZIhvcNAQEEBQAwazELMAkGA1UEBhMCREUx
+EzARBgNVBAcUCkT8c3NlbGRvcmYxFjAUBgNVBAoTDWcxMCBDb2RlIEdtYkgxGTAX
+BgNVBAsTEEFlZ3lwdGVuIFByb2plY3QxFDASBgNVBAMTC3Rlc3QgY2VydCAxMB4X
+DTAxMTIwMzA5MzYzOFoXDTAyMTIwMzA5MzYzOFowazELMAkGA1UEBhMCREUxEzAR
+BgNVBAcUCkT8c3NlbGRvcmYxFjAUBgNVBAoTDWcxMCBDb2RlIEdtYkgxGTAXBgNV
+BAsTEEFlZ3lwdGVuIFByb2plY3QxFDASBgNVBAMTC3Rlc3QgY2VydCAxMIGfMA0G
+CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgzpb5C2yeAvOSK+rak/5QqHXqxrzBi7mp
+zy6EllyqLR/5Wn9UJGXGwMGdJ25FJs4EiGinqRT9NDzDqH3XQpH/xWVQbVu7Jcus
+ag4t0fi8qrDUopwvN8lQ82NIS/Jp94kUQEZLr3mCfgOjbnC4FJOO69xj6WQke+dd
+xYsBS36iUQIDAQABo4HIMIHFMB0GA1UdDgQWBBQzN40SkcBUcYM4Xwhlv6lL+Y40
+8zCBlQYDVR0jBIGNMIGKgBQzN40SkcBUcYM4Xwhlv6lL+Y4086FvpG0wazELMAkG
+A1UEBhMCREUxEzARBgNVBAcUCkT8c3NlbGRvcmYxFjAUBgNVBAoTDWcxMCBDb2Rl
+IEdtYkgxGTAXBgNVBAsTEEFlZ3lwdGVuIFByb2plY3QxFDASBgNVBAMTC3Rlc3Qg
+Y2VydCAxggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAbIcEHoo4
+qNobF2cWRCBaDZXQ6XcXG1lMLObrTSe4asUK++H59nC/ax+wMnDVrWZ8gkwJO1Ks
+HGx98+gjaCR+lP5P/yE5O8PD7TOp8OiYZVyw/guuQYn4qeondibUUMJeJCf7T6cf
+v+NjLpIt8lRTfgRBhT6SOoXSZodR8/NZPBkxggFXMIIBUwIBATBwMGsxCzAJBgNV
+BAYTAkRFMRMwEQYDVQQHFApE/HNzZWxkb3JmMRYwFAYDVQQKEw1nMTAgQ29kZSBH
+bWJIMRkwFwYDVQQLExBBZWd5cHRlbiBQcm9qZWN0MRQwEgYDVQQDEwt0ZXN0IGNl
+cnQgMQIBADAHBgUrDgMCGqBDMBwGCSqGSIb3DQEJBTEPFw0wMjA4MDgxMjM4MjJa
+MCMGCSqGSIb3DQEJBDEWBBSzI9M4i+WJMTDoCeLulJP7p1PCezALBgkqhkiG9w0B
+AQEEgYAqoJR3uJkChUhaH0EH3U5JpQApIhVEqedaKPT6BCPPWALFPzEa6YKzftA5
+e+Dap41UnB8nQ9rfwYty3hw5EulzV9iLnhGornQIgI6D5o7ymxyacsiYEarezxGX
+juPMnyXcpTOgt+vz2k3qisjzxU32zpsOuK6U82PSHysX8rH9QgAAAAAAAA==
+-----END SIGNED MESSAGE-----
diff --git a/tests/text-2.txt b/tests/text-2.txt
new file mode 100644
index 0000000..314c7a4
--- /dev/null
+++ b/tests/text-2.txt
@@ -0,0 +1,2 @@
+Military intelligence is a contradiction in terms.
+ -- Groucho Marx
diff --git a/tests/text-3.txt b/tests/text-3.txt
new file mode 100644
index 0000000..9345b55
--- /dev/null
+++ b/tests/text-3.txt
@@ -0,0 +1,2 @@
+Military justice is to justice what military music is to music.
+ -- Groucho Marx