提交 e94dd6ab 编写于 作者: B Bruce Momjian

Add missing pgcrypto files from previous commit.

上级 42e7b0f0
--
-- PGP Armor
--
select armor('');
armor
---------------------------------------------------------------
-----BEGIN PGP MESSAGE-----
=twTO
-----END PGP MESSAGE-----
(1 row)
select armor('test');
armor
------------------------------------------------------------------------
-----BEGIN PGP MESSAGE-----
dGVzdA==
=+G7Q
-----END PGP MESSAGE-----
(1 row)
select dearmor(armor(''));
dearmor
---------
(1 row)
select dearmor(armor('zooka'));
dearmor
---------
zooka
(1 row)
select armor('0123456789abcdef0123456789abcdef0123456789abcdef
0123456789abcdef0123456789abcdef0123456789abcdef');
armor
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----BEGIN PGP MESSAGE-----
MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmCjAxMjM0NTY3
ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmMDEyMzQ1Njc4OWFiY2RlZg==
=JFw5
-----END PGP MESSAGE-----
(1 row)
-- lots formatting
select dearmor(' a pgp msg:
-----BEGIN PGP MESSAGE-----
Comment: Some junk
em9va2E=
=D5cR
-----END PGP MESSAGE-----');
dearmor
---------
zooka
(1 row)
-- lots messages
select dearmor('
wrong packet:
-----BEGIN PGP MESSAGE-----
d3Jvbmc=
=vCYP
-----END PGP MESSAGE-----
right packet:
-----BEGIN PGP MESSAGE-----
cmlnaHQ=
=nbpj
-----END PGP MESSAGE-----
use only first packet
-----BEGIN PGP MESSAGE-----
d3Jvbmc=
=vCYP
-----END PGP MESSAGE-----
');
dearmor
---------
right
(1 row)
-- bad crc
select dearmor('
-----BEGIN PGP MESSAGE-----
em9va2E=
=ZZZZ
-----END PGP MESSAGE-----
');
ERROR: dearmor: Corrupt ascii-armor
--
-- PGP compression support
--
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
ww0ECQMCsci6AdHnELlh0kQB4jFcVwHMJg0Bulop7m3Mi36s15TAhBo0AnzIrRFrdLVCkKohsS6+
DMcmR53SXfLoDJOv/M8uKj3QSq7oWNIp95pxfA==
=tbSn
-----END PGP MESSAGE-----
'), 'key', 'expect-compress-algo=1');
pgp_sym_decrypt
-----------------
Secret message
(1 row)
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret message', 'key', 'compress-algo=0'),
'key', 'expect-compress-algo=0');
pgp_sym_decrypt
-----------------
Secret message
(1 row)
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret message', 'key', 'compress-algo=1'),
'key', 'expect-compress-algo=1');
pgp_sym_decrypt
-----------------
Secret message
(1 row)
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret message', 'key', 'compress-algo=2'),
'key', 'expect-compress-algo=2');
pgp_sym_decrypt
-----------------
Secret message
(1 row)
-- level=0 should turn compression off
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret message', 'key',
'compress-algo=2, compress-level=0'),
'key', 'expect-compress-algo=0');
pgp_sym_decrypt
-----------------
Secret message
(1 row)
--
-- pgp_descrypt tests
--
-- Checking ciphers
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.blowfish.sha1.mdc.s2k3.z0
jA0EBAMCfFNwxnvodX9g0jwB4n4s26/g5VmKzVab1bX1SmwY7gvgvlWdF3jKisvS
yA6Ce1QTMK3KdL2MPfamsTUSAML8huCJMwYQFfE=
=JcP+
-----END PGP MESSAGE-----
'), 'foobar');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes.sha1.mdc.s2k3.z0
jA0EBwMCci97v0Q6Z0Zg0kQBsVf5Oe3iC+FBzUmuMV9KxmAyOMyjCc/5i8f1Eest
UTAsG35A1vYs02VARKzGz6xI2UHwFUirP+brPBg3Ee7muOx8pA==
=XtrP
-----END PGP MESSAGE-----
'), 'foobar');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes192.sha1.mdc.s2k3.z0
jA0ECAMCI7YQpWqp3D1g0kQBCjB7GlX7+SQeXNleXeXQ78ZAPNliquGDq9u378zI
5FPTqAhIB2/2fjY8QEIs1ai00qphjX2NitxV/3Wn+6dufB4Q4g==
=rCZt
-----END PGP MESSAGE-----
'), 'foobar');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes256.sha1.mdc.s2k3.z0
jA0ECQMC4f/5djqCC1Rg0kQBTHEPsD+Sw7biBsM2er3vKyGPAQkuTBGKC5ie7hT/
lceMfQdbAg6oTFyJpk/wH18GzRDphCofg0X8uLgkAKMrpcmgog==
=fB6S
-----END PGP MESSAGE-----
'), 'foobar');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
-- Checking MDC modes
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes.sha1.nomdc.s2k3.z0
jA0EBwMCnv07rlXqWctgyS2Dm2JfOKCRL4sLSLJUC8RS2cH7cIhKSuLitOtyquB+
u9YkgfJfsuRJmgQ9tmo=
=60ui
-----END PGP MESSAGE-----
'), 'foobar');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes.sha1.mdc.s2k3.z0
jA0EBwMCEeP3idNjQ1Bg0kQBf4G0wX+2QNzLh2YNwYkQgQkfYhn/hLXjV4nK9nsE
8Ex1Dsdt5UPvOz8W8VKQRS6loOfOe+yyXil8W3IYFwUpdDUi+Q==
=moGf
-----END PGP MESSAGE-----
'), 'foobar');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
-- Checking hashes
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes.md5.mdc.s2k3.z0
jA0EBwMClrXXtOXetohg0kQBn0Kl1ymevQZRHkdoYRHgzCwSQEiss7zYff2UNzgO
KyRrHf7zEBuZiZ2AG34jNVMOLToj1jJUg5zTSdecUzQVCykWTA==
=NyLk
-----END PGP MESSAGE-----
'), 'foobar');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes.sha1.mdc.s2k3.z0
jA0EBwMCApbdlrURoWJg0kQBzHM/E0o7djY82bNuspjxjAcPFrrtp0uvDdMQ4z2m
/PM8jhgI5vxFYfNQjLl8y3fHYIomk9YflN9K/Q13iq8A8sjeTw==
=FxbQ
-----END PGP MESSAGE-----
'), 'foobar');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
-- Checking S2K modes
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes.sha1.mdc.s2k0.z0
jAQEBwAC0kQBKTaLAKE3xzps+QIZowqRNb2eAdzBw2LxEW2YD5PgNlbhJdGg+dvw
Ah9GXjGS1TVALzTImJbz1uHUZRfhJlFbc5yGQw==
=YvkV
-----END PGP MESSAGE-----
'), 'foobar');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes.sha1.mdc.s2k1.z0
jAwEBwEC/QTByBLI3b/SRAHPxKzI6SZBo5lAEOD+EsvKQWO4adL9tDY+++Iqy1xK
4IaWXVKEj9R2Lr2xntWWMGZtcKtjD2lFFRXXd9dZp1ZThNDz
=dbXm
-----END PGP MESSAGE-----
'), 'foobar');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes.sha1.mdc.s2k3.z0
jA0EBwMCEq4Su3ZqNEJg0kQB4QG5jBTKF0i04xtH+avzmLhstBNRxvV3nsmB3cwl
z+9ZaA/XdSx5ZiFnMym8P6r8uY9rLjjNptvvRHlxIReF+p9MNg==
=VJKg
-----END PGP MESSAGE-----
'), 'foobar');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes192.sha1.mdc.s2k0.z0
jAQECAAC0kQBBDnQWkgsx9YFaqDfWmpsiyAJ6y2xG/sBvap1dySYEMuZ+wJTXQ9E
Cr3i2M7TgVZ0M4jp4QL0adG1lpN5iK7aQeOwMw==
=cg+i
-----END PGP MESSAGE-----
'), 'foobar');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes192.sha1.mdc.s2k1.z0
jAwECAECruOfyNDFiTnSRAEVoGXm4A9UZKkWljdzjEO/iaE7mIraltIpQMkiqCh9
7h8uZ2u9uRBOv222fZodGvc6bvq/4R4hAa/6qSHtm8mdmvGt
=aHmC
-----END PGP MESSAGE-----
'), 'foobar');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes192.sha1.mdc.s2k3.z0
jA0ECAMCjFn6SRi3SONg0kQBqtSHPaD0m7rXfDAhCWU/ypAsI93GuHGRyM99cvMv
q6eF6859ZVnli3BFSDSk3a4e/pXhglxmDYCfjAXkozKNYLo6yw==
=K0LS
-----END PGP MESSAGE-----
'), 'foobar');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes256.sha1.mdc.s2k0.z0
jAQECQAC0kQB4L1eMbani07XF2ZYiXNK9LW3v8w41oUPl7dStmrJPQFwsdxmrDHu
rQr3WbdKdY9ufjOE5+mXI+EFkSPrF9rL9NCq6w==
=RGts
-----END PGP MESSAGE-----
'), 'foobar');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes256.sha1.mdc.s2k1.z0
jAwECQECKHhrou7ZOIXSRAHWIVP+xjVQcjAVBTt+qh9SNzYe248xFTwozkwev3mO
+KVJW0qhk0An+Y2KF99/bYFl9cL5D3Tl43fC8fXGl3x3m7pR
=SUrU
-----END PGP MESSAGE-----
'), 'foobar');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes256.sha1.mdc.s2k3.z0
jA0ECQMCjc8lwZu8Fz1g0kQBkEzjImi21liep5jj+3dAJ2aZFfUkohi8b3n9z+7+
4+NRzL7cMW2RLAFnJbiqXDlRHMwleeuLN1up2WIxsxtYYuaBjA==
=XZrG
-----END PGP MESSAGE-----
'), 'foobar');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
-- Checking longer passwords
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes.sha1.mdc.s2k3.z0
jA0EBwMCx6dBiuqrYNRg0kQBEo63AvA1SCslxP7ayanLf1H0/hlk2nONVhTwVEWi
tTGup1mMz6Cfh1uDRErUuXpx9A0gdMu7zX0o5XjrL7WGDAZdSw==
=XKKG
-----END PGP MESSAGE-----
'), '0123456789abcdefghij');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes.sha1.mdc.s2k3.z0
jA0EBwMCBDvYuS990iFg0kQBW31UK5OiCjWf5x6KJ8qNNT2HZWQCjCBZMU0XsOC6
CMxFKadf144H/vpoV9GA0f22keQgCl0EsTE4V4lweVOPTKCMJg==
=gWDh
-----END PGP MESSAGE-----
'), '0123456789abcdefghij2jk4h5g2j54khg23h54g2kh54g2khj54g23hj54');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes.sha1.mdc.s2k3.z0
jA0EBwMCqXbFafC+ofVg0kQBejyiPqH0QMERVGfmPOjtAxvyG5KDIJPYojTgVSDt
FwsDabdQUz5O7bgNSnxfmyw1OifGF+W2bIn/8W+0rDf8u3+O+Q==
=OxOF
-----END PGP MESSAGE-----
'), 'x');
pgp_sym_decrypt
-----------------
Secret message.
(1 row)
-- Checking various data
select encode(digest(pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat1.aes.sha1.mdc.s2k3.z0
jA0EBwMCGJ+SpuOysINg0kQBJfSjzsW0x4OVcAyr17O7FBvMTwIGeGcJd99oTQU8
Xtx3kDqnhUq9Z1fS3qPbi5iNP2A9NxOBxPWz2JzxhydANlgbxg==
=W/ik
-----END PGP MESSAGE-----
'), '0123456789abcdefghij'), 'sha1'), 'hex');
encode
------------------------------------------
0225e3ede6f2587b076d021a189ff60aad67e066
(1 row)
-- expected: 0225e3ede6f2587b076d021a189ff60aad67e066
select encode(digest(pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat2.aes.sha1.mdc.s2k3.z0
jA0EBwMCvdpDvidNzMxg0jUBvj8eS2+1t/9/zgemxvhtc0fvdKGGbjH7dleaTJRB
SaV9L04ky1qECNDx3XjnoKLC+H7IOQ==
=Fxen
-----END PGP MESSAGE-----
'), '0123456789abcdefghij'), 'sha1'), 'hex');
encode
------------------------------------------
da39a3ee5e6b4b0d3255bfef95601890afd80709
(1 row)
-- expected: da39a3ee5e6b4b0d3255bfef95601890afd80709
select encode(digest(pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: dat3.aes.sha1.mdc.s2k3.z0
jA0EBwMCxQvxJZ3G/HRg0lgBeYmTa7/uDAjPyFwSX4CYBgpZWVn/JS8JzILrcWF8
gFnkUKIE0PSaYFp+Yi1VlRfUtRQ/X/LYNGa7tWZS+4VQajz2Xtz4vUeAEiYFYPXk
73Hb8m1yRhQK
=ivrD
-----END PGP MESSAGE-----
'), '0123456789abcdefghij'), 'sha1'), 'hex');
encode
------------------------------------------
5e5c135efc0dd00633efc6dfd6e731ea408a5b4c
(1 row)
-- expected: 5e5c135efc0dd00633efc6dfd6e731ea408a5b4c
-- Checking CRLF
select encode(digest(pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: crlf mess
ww0ECQMCt7VAtby6l4Bi0lgB5KMIZiiF/b3CfMfUyY0eDncsGXtkbu1X+l9brjpMP8eJnY79Amms
a3nsOzKTXUfS9VyaXo8IrncM6n7fdaXpwba/3tNsAhJG4lDv1k4g9v8Ix2dfv6Rs
=mBP9
-----END PGP MESSAGE-----
'), 'key', 'convert-crlf=0'), 'sha1'), 'hex');
encode
------------------------------------------
9353062be7720f1446d30b9e75573a4833886784
(1 row)
-- expected: 9353062be7720f1446d30b9e75573a4833886784
select encode(digest(pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
Comment: crlf mess
ww0ECQMCt7VAtby6l4Bi0lgB5KMIZiiF/b3CfMfUyY0eDncsGXtkbu1X+l9brjpMP8eJnY79Amms
a3nsOzKTXUfS9VyaXo8IrncM6n7fdaXpwba/3tNsAhJG4lDv1k4g9v8Ix2dfv6Rs
=mBP9
-----END PGP MESSAGE-----
'), 'key', 'convert-crlf=1'), 'sha1'), 'hex');
encode
------------------------------------------
7efefcab38467f7484d6fa43dc86cf5281bd78e2
(1 row)
-- expected: 7efefcab38467f7484d6fa43dc86cf5281bd78e2
--
-- PGP encrypt
--
select pgp_sym_decrypt(pgp_sym_encrypt('Secret.', 'key'), 'key');
pgp_sym_decrypt
-----------------
Secret.
(1 row)
-- check whether the defaults are ok
select pgp_sym_decrypt(pgp_sym_encrypt('Secret.', 'key'),
'key', 'expect-cipher-algo=aes128,
expect-disable-mdc=0,
expect-sess-key=0,
expect-s2k-mode=3,
expect-s2k-digest-algo=sha1,
expect-compress-algo=0
');
pgp_sym_decrypt
-----------------
Secret.
(1 row)
-- maybe the expect- stuff simply does not work
select pgp_sym_decrypt(pgp_sym_encrypt('Secret.', 'key'),
'key', 'expect-cipher-algo=bf,
expect-disable-mdc=1,
expect-sess-key=1,
expect-s2k-mode=0,
expect-s2k-digest-algo=md5,
expect-compress-algo=1
');
NOTICE: pgp_decrypt: unexpected cipher_algo: expected 4 got 7
NOTICE: pgp_decrypt: unexpected s2k_mode: expected 0 got 3
NOTICE: pgp_decrypt: unexpected s2k_digest_algo: expected 1 got 2
NOTICE: pgp_decrypt: unexpected use_sess_key: expected 1 got 0
NOTICE: pgp_decrypt: unexpected disable_mdc: expected 1 got 0
NOTICE: pgp_decrypt: unexpected compress_algo: expected 1 got 0
pgp_sym_decrypt
-----------------
Secret.
(1 row)
-- bytea as text
select pgp_sym_decrypt(pgp_sym_encrypt_bytea('Binary', 'baz'), 'baz');
ERROR: pgp_decrypt error: Not text data
-- text as bytea
select pgp_sym_decrypt_bytea(pgp_sym_encrypt('Text', 'baz'), 'baz');
pgp_sym_decrypt_bytea
-----------------------
Text
(1 row)
-- algorithm change
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret.', 'key', 'cipher-algo=bf'),
'key', 'expect-cipher-algo=bf');
pgp_sym_decrypt
-----------------
Secret.
(1 row)
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret.', 'key', 'cipher-algo=aes'),
'key', 'expect-cipher-algo=aes128');
pgp_sym_decrypt
-----------------
Secret.
(1 row)
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret.', 'key', 'cipher-algo=aes192'),
'key', 'expect-cipher-algo=aes192');
pgp_sym_decrypt
-----------------
Secret.
(1 row)
-- s2k change
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret.', 'key', 's2k-mode=0'),
'key', 'expect-s2k-mode=0');
pgp_sym_decrypt
-----------------
Secret.
(1 row)
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret.', 'key', 's2k-mode=1'),
'key', 'expect-s2k-mode=1');
pgp_sym_decrypt
-----------------
Secret.
(1 row)
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret.', 'key', 's2k-mode=3'),
'key', 'expect-s2k-mode=3');
pgp_sym_decrypt
-----------------
Secret.
(1 row)
-- s2k digest change
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret.', 'key', 's2k-digest-algo=md5'),
'key', 'expect-s2k-digest-algo=md5');
pgp_sym_decrypt
-----------------
Secret.
(1 row)
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret.', 'key', 's2k-digest-algo=sha1'),
'key', 'expect-s2k-digest-algo=sha1');
pgp_sym_decrypt
-----------------
Secret.
(1 row)
-- sess key
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret.', 'key', 'sess-key=0'),
'key', 'expect-sess-key=0');
pgp_sym_decrypt
-----------------
Secret.
(1 row)
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret.', 'key', 'sess-key=1'),
'key', 'expect-sess-key=1');
pgp_sym_decrypt
-----------------
Secret.
(1 row)
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret.', 'key', 'sess-key=1, cipher-algo=bf'),
'key', 'expect-sess-key=1, expect-cipher-algo=bf');
pgp_sym_decrypt
-----------------
Secret.
(1 row)
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret.', 'key', 'sess-key=1, cipher-algo=aes192'),
'key', 'expect-sess-key=1, expect-cipher-algo=aes192');
pgp_sym_decrypt
-----------------
Secret.
(1 row)
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret.', 'key', 'sess-key=1, cipher-algo=aes256'),
'key', 'expect-sess-key=1, expect-cipher-algo=aes256');
pgp_sym_decrypt
-----------------
Secret.
(1 row)
-- no mdc
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret.', 'key', 'disable-mdc=1'),
'key', 'expect-disable-mdc=1');
pgp_sym_decrypt
-----------------
Secret.
(1 row)
-- crlf
select encode(pgp_sym_decrypt_bytea(
pgp_sym_encrypt('1\n2\n3\r\n', 'key', 'convert-crlf=1'),
'key'), 'hex');
encode
----------------------
310d0a320d0a330d0d0a
(1 row)
-- conversion should be lossless
select encode(digest(pgp_sym_decrypt(
pgp_sym_encrypt('\r\n0\n1\r\r\n\n2\r', 'key', 'convert-crlf=1'),
'key', 'convert-crlf=1'), 'sha1'), 'hex') as result,
encode(digest('\r\n0\n1\r\r\n\n2\r', 'sha1'), 'hex') as expect;
result | expect
------------------------------------------+------------------------------------------
47bde5d88d6ef8770572b9cbb4278b402aa69966 | 47bde5d88d6ef8770572b9cbb4278b402aa69966
(1 row)
--
-- PGP info functions
--
-- pgp_key_id
select pgp_key_id(dearmor(pubkey)) from keytbl where id=1;
pgp_key_id
------------------
D936CF64BB73F466
(1 row)
select pgp_key_id(dearmor(pubkey)) from keytbl where id=2;
pgp_key_id
------------------
2C226E1FFE5CC7D4
(1 row)
select pgp_key_id(dearmor(pubkey)) from keytbl where id=3;
pgp_key_id
------------------
B68504FD128E1FF9
(1 row)
select pgp_key_id(dearmor(pubkey)) from keytbl where id=4; -- should fail
ERROR: No usable key found (expecting Elgamal key)
select pgp_key_id(dearmor(pubkey)) from keytbl where id=5;
pgp_key_id
------------------
D936CF64BB73F466
(1 row)
select pgp_key_id(dearmor(seckey)) from keytbl where id=1;
pgp_key_id
------------------
D936CF64BB73F466
(1 row)
select pgp_key_id(dearmor(seckey)) from keytbl where id=2;
pgp_key_id
------------------
2C226E1FFE5CC7D4
(1 row)
select pgp_key_id(dearmor(seckey)) from keytbl where id=3;
pgp_key_id
------------------
B68504FD128E1FF9
(1 row)
select pgp_key_id(dearmor(seckey)) from keytbl where id=4; -- should fail
ERROR: No usable key found (expecting Elgamal key)
select pgp_key_id(dearmor(seckey)) from keytbl where id=5;
pgp_key_id
------------------
D936CF64BB73F466
(1 row)
select pgp_key_id(dearmor(data)) as data_key_id
from encdata order by id;
data_key_id
------------------
D936CF64BB73F466
2C226E1FFE5CC7D4
B68504FD128E1FF9
(3 rows)
此差异已折叠。
--
-- PGP Public Key Encryption
--
-- successful encrypt/decrypt
select pgp_pub_decrypt(
pgp_pub_encrypt('Secret msg', dearmor(pubkey)),
dearmor(seckey))
from keytbl where keytbl.id=1;
pgp_pub_decrypt
-----------------
Secret msg
(1 row)
select pgp_pub_decrypt(
pgp_pub_encrypt('Secret msg', dearmor(pubkey)),
dearmor(seckey))
from keytbl where keytbl.id=2;
pgp_pub_decrypt
-----------------
Secret msg
(1 row)
select pgp_pub_decrypt(
pgp_pub_encrypt('Secret msg', dearmor(pubkey)),
dearmor(seckey))
from keytbl where keytbl.id=3;
pgp_pub_decrypt
-----------------
Secret msg
(1 row)
-- try with rsa-sign only
select pgp_pub_decrypt(
pgp_pub_encrypt('Secret msg', dearmor(pubkey)),
dearmor(seckey))
from keytbl where keytbl.id=4;
ERROR: pgp_encrypt error: No usable key found (expecting Elgamal key)
-- try with secret key
select pgp_pub_decrypt(
pgp_pub_encrypt('Secret msg', dearmor(seckey)),
dearmor(seckey))
from keytbl where keytbl.id=1;
ERROR: pgp_encrypt error: Refusing to encrypt with secret key
-- does text-to-bytea works
select pgp_pub_decrypt_bytea(
pgp_pub_encrypt('Secret msg', dearmor(pubkey)),
dearmor(seckey))
from keytbl where keytbl.id=1;
pgp_pub_decrypt_bytea
-----------------------
Secret msg
(1 row)
-- and bytea-to-text?
select pgp_pub_decrypt(
pgp_pub_encrypt_bytea('Secret msg', dearmor(pubkey)),
dearmor(seckey))
from keytbl where keytbl.id=1;
ERROR: pgp_decrypt error: Not text data
--
-- SHA2 family
--
-- SHA256
SELECT encode(digest('', 'sha256'), 'hex');
encode
------------------------------------------------------------------
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
(1 row)
SELECT encode(digest('a', 'sha256'), 'hex');
encode
------------------------------------------------------------------
ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb
(1 row)
SELECT encode(digest('abc', 'sha256'), 'hex');
encode
------------------------------------------------------------------
ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
(1 row)
SELECT encode(digest('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', 'sha256'), 'hex');
encode
------------------------------------------------------------------
248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1
(1 row)
SELECT encode(digest('12345678901234567890123456789012345678901234567890123456789012345678901234567890', 'sha256'), 'hex');
encode
------------------------------------------------------------------
f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e
(1 row)
-- SHA384
SELECT encode(digest('', 'sha384'), 'hex');
encode
--------------------------------------------------------------------------------------------------
38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b
(1 row)
SELECT encode(digest('a', 'sha384'), 'hex');
encode
--------------------------------------------------------------------------------------------------
54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31
(1 row)
SELECT encode(digest('abc', 'sha384'), 'hex');
encode
--------------------------------------------------------------------------------------------------
cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7
(1 row)
SELECT encode(digest('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', 'sha384'), 'hex');
encode
--------------------------------------------------------------------------------------------------
3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b
(1 row)
SELECT encode(digest('abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu', 'sha384'), 'hex');
encode
--------------------------------------------------------------------------------------------------
09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039
(1 row)
SELECT encode(digest('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz', 'sha384'), 'hex');
encode
--------------------------------------------------------------------------------------------------
3d208973ab3508dbbd7e2c2862ba290ad3010e4978c198dc4d8fd014e582823a89e16f9b2a7bbc1ac938e2d199e8bea4
(1 row)
-- SHA512
SELECT encode(digest('', 'sha512'), 'hex');
encode
----------------------------------------------------------------------------------------------------------------------------------
cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e
(1 row)
SELECT encode(digest('a', 'sha512'), 'hex');
encode
----------------------------------------------------------------------------------------------------------------------------------
1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75
(1 row)
SELECT encode(digest('abc', 'sha512'), 'hex');
encode
----------------------------------------------------------------------------------------------------------------------------------
ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f
(1 row)
SELECT encode(digest('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', 'sha512'), 'hex');
encode
----------------------------------------------------------------------------------------------------------------------------------
204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445
(1 row)
SELECT encode(digest('abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu', 'sha512'), 'hex');
encode
----------------------------------------------------------------------------------------------------------------------------------
8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909
(1 row)
SELECT encode(digest('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz', 'sha512'), 'hex');
encode
----------------------------------------------------------------------------------------------------------------------------------
930d0cefcb30ff1133b6898121f1cf3d27578afcafe8677c5257cf069911f75d8f5831b56ebfda67b278e66dff8b84fe2b2870f742a580d8edb41987232850c9
(1 row)
/*
* fortuna.c
* Fortuna-like PRNG.
*
* Copyright (c) 2005 Marko Kreen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/fortuna.c,v 1.1 2005/07/10 13:46:27 momjian Exp $
*/
#include <postgres.h>
#include <sys/time.h>
#include <time.h>
#include "rijndael.h"
#include "sha2.h"
#include "fortuna.h"
/*
* Why Fortuna-like: There does not seem to be any definitive reference
* on Fortuna in the net. Instead this implementation is based on
* following references:
*
* http://en.wikipedia.org/wiki/Fortuna_(PRNG)
* - Wikipedia article
* http://jlcooke.ca/random/
* - Jean-Luc Cooke Fortuna-based /dev/random driver for Linux.
*/
/*
* There is some confusion about whether and how to carry forward
* the state of the pools. Seems like original Fortuna does not
* do it, resetting hash after each request. I guess expecting
* feeding to happen more often that requesting. This is absolutely
* unsuitable for pgcrypto, as nothing asynchronous happens here.
*
* J.L. Cooke fixed this by feeding previous hash to new re-initialized
* hash context.
*
* Fortuna predecessor Yarrow requires ability to query intermediate
* 'final result' from hash, without affecting it.
*
* This implementation uses the Yarrow method - asking intermediate
* results, but continuing with old state.
*/
/*
* Algorithm parameters
*/
/*
* How many pools.
*
* Original Fortuna uses 32 pools, that means 32'th pool is
* used not earlier than in 13th year. This is a waste in
* pgcrypto, as we have very low-frequancy seeding. Here
* is preferable to have all entropy usable in reasonable time.
*
* With 23 pools, 23th pool is used after 9 days which seems
* more sane.
*
* In our case the minimal cycle time would be bit longer
* than the system-randomness feeding frequency.
*/
#define NUM_POOLS 23
/* in microseconds */
#define RESEED_INTERVAL 100000 /* 0.1 sec */
/* for one big request, reseed after this many bytes */
#define RESEED_BYTES (1024*1024)
/*
* Algorithm constants
*/
/* max sources */
#define MAX_SOURCES 8
/* Both cipher key size and hash result size */
#define BLOCK 32
/* cipher block size */
#define CIPH_BLOCK 16
/* for internal wrappers */
#define MD_CTX SHA256_CTX
#define CIPH_CTX rijndael_ctx
struct fortuna_state {
uint8 counter[CIPH_BLOCK];
uint8 result[CIPH_BLOCK];
uint8 key[BLOCK];
MD_CTX pool[NUM_POOLS];
CIPH_CTX ciph;
unsigned source_pos[MAX_SOURCES];
unsigned reseed_count;
struct timeval last_reseed_time;
};
typedef struct fortuna_state FState;
/*
* Use our own wrappers here.
* - Need to get intermediate result from digest, without affecting it.
* - Need re-set key on a cipher context.
* - Algorithms are guaranteed to exist.
* - No memory allocations.
*/
static void ciph_init(CIPH_CTX *ctx, const uint8 *key, int klen)
{
rijndael_set_key(ctx, (const uint32 *)key, klen, 1);
}
static void ciph_encrypt(CIPH_CTX *ctx, const uint8 *in, uint8 *out)
{
rijndael_encrypt(ctx, (const uint32 *)in, (uint32 *)out);
}
static void md_init(MD_CTX *ctx)
{
SHA256_Init(ctx);
}
static void md_update(MD_CTX *ctx, const uint8 *data, int len)
{
SHA256_Update(ctx, data, len);
}
static void md_result(MD_CTX *ctx, uint8 *dst)
{
SHA256_CTX tmp;
memcpy(&tmp, ctx, sizeof(*ctx));
SHA256_Final(dst, &tmp);
memset(&tmp, 0, sizeof(tmp));
}
/*
* initialize state
*/
static void init_state(FState *st)
{
int i;
memset(st, 0, sizeof(*st));
for (i = 0; i < NUM_POOLS; i++)
md_init(&st->pool[i]);
}
/*
* Must not reseed more ofter than RESEED_PER_SEC
* times per second.
*/
static int too_often(FState *st)
{
int ok;
struct timeval tv;
struct timeval *last = &st->last_reseed_time;
gettimeofday(&tv, NULL);
ok = 0;
if (tv.tv_sec != last->tv_sec)
ok = 1;
else if (tv.tv_usec - last->tv_usec >= RESEED_INTERVAL)
ok = 1;
memcpy(last, &tv, sizeof(tv));
memset(&tv, 0, sizeof(tv));
return ok;
}
/*
* generate new key from all the pools
*/
static void reseed(FState *st)
{
unsigned k;
unsigned n;
MD_CTX key_md;
uint8 buf[BLOCK];
/* check frequency */
if (too_often(st))
return;
/*
* Both #0 and #1 reseed would use only pool 0.
* Just skip #0 then.
*/
n = ++st->reseed_count;
/*
* The goal: use k-th pool only 1/(2^k) of the time.
*/
md_init(&key_md);
for (k = 0; k < NUM_POOLS; k++) {
md_result(&st->pool[k], buf);
md_update(&key_md, buf, BLOCK);
if (n & 1 || !n)
break;
n >>= 1;
}
/* add old key into mix too */
md_update(&key_md, st->key, BLOCK);
/* now we have new key */
md_result(&key_md, st->key);
/* use new key */
ciph_init(&st->ciph, st->key, BLOCK);
memset(&key_md, 0, sizeof(key_md));
memset(buf, 0, BLOCK);
n = k = 0;
}
/*
* update pools
*/
static void add_entropy(FState *st, unsigned src_id, const uint8 *data, unsigned len)
{
unsigned pos;
uint8 hash[BLOCK];
MD_CTX md;
/* just in case there's a bug somewhere */
if (src_id >= MAX_SOURCES)
src_id = USER_ENTROPY;
/* hash given data */
md_init(&md);
md_update(&md, data, len);
md_result(&md, hash);
/* update pools round-robin manner */
pos = st->source_pos[src_id];
md_update( &st->pool[pos], hash, BLOCK);
if (++pos >= NUM_POOLS)
pos = 0;
st->source_pos[src_id] = pos;
memset(hash, 0, BLOCK);
memset(&md, 0, sizeof(md));
}
/*
* Endianess does not matter.
* It just needs to change without repeating.
*/
static void inc_counter(FState *st)
{
uint32 *val = (uint32*)st->counter;
if (++val[0])
return;
if (++val[1])
return;
if (++val[2])
return;
++val[3];
}
static void extract_data(FState *st, unsigned count, uint8 *dst)
{
unsigned n;
unsigned block_nr = 0;
/*
* Every request should be with different key,
* if possible.
*/
reseed(st);
/*
* If the reseed didn't happen, don't use the old data
* rather encrypt again.
*/
while (count > 0) {
/* must not give out too many bytes with one key */
if (block_nr > (RESEED_BYTES / CIPH_BLOCK))
{
reseed(st);
block_nr = 0;
}
/* produce bytes */
ciph_encrypt(&st->ciph, st->counter, st->result);
block_nr++;
/* prepare for next time */
inc_counter(st);
/* copy result */
if (count > CIPH_BLOCK)
n = CIPH_BLOCK;
else
n = count;
memcpy(dst, st->result, n);
dst += n;
count -= n;
}
}
/*
* public interface
*/
static FState main_state;
static int init_done = 0;
void fortuna_add_entropy(unsigned src_id, const uint8 *data, unsigned len)
{
if (!init_done)
{
init_state(&main_state);
init_done = 1;
}
if (!data || !len)
return;
add_entropy(&main_state, src_id, data, len);
}
void fortuna_get_bytes(unsigned len, uint8 *dst)
{
if (!init_done)
{
init_state(&main_state);
init_done = 1;
}
if (!dst || !len)
return;
extract_data(&main_state, len, dst);
}
/*
* fortuna.c
* Fortuna PRNG.
*
* Copyright (c) 2005 Marko Kreen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/fortuna.h,v 1.1 2005/07/10 13:46:28 momjian Exp $
*/
#ifndef __FORTUNA_H
#define __FORTUNA_H
/*
* Event source ID's
*/
#define SYSTEM_ENTROPY 0
#define USER_ENTROPY 1
void fortuna_get_bytes(unsigned len, uint8 *dst);
void fortuna_add_entropy(unsigned src_id, const uint8 *data, unsigned len);
#endif
/*
* mbuf.c
* Memory buffer operations.
*
* Copyright (c) 2005 Marko Kreen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/mbuf.c,v 1.1 2005/07/10 13:46:28 momjian Exp $
*/
#include <postgres.h>
#include "px.h"
#include "mbuf.h"
#define STEP (16*1024)
struct MBuf
{
uint8 *data;
uint8 *data_end;
uint8 *read_pos;
uint8 *buf_end;
int no_write:1;
int own_data:1;
};
int
mbuf_avail(MBuf * mbuf)
{
return mbuf->data_end - mbuf->read_pos;
}
int
mbuf_size(MBuf * mbuf)
{
return mbuf->data_end - mbuf->data;
}
int
mbuf_tell(MBuf * mbuf)
{
return mbuf->read_pos - mbuf->data;
}
int
mbuf_free(MBuf * mbuf)
{
if (mbuf->own_data)
{
memset(mbuf->data, 0, mbuf->buf_end - mbuf->data);
px_free(mbuf->data);
}
px_free(mbuf);
return 0;
}
static void
prepare_room(MBuf * mbuf, int block_len)
{
uint8 *newbuf;
unsigned newlen;
if (mbuf->data_end + block_len <= mbuf->buf_end)
return;
newlen = (mbuf->buf_end - mbuf->data)
+ ((block_len + STEP + STEP - 1) & -STEP);
newbuf = px_realloc(mbuf->data, newlen);
mbuf->buf_end = newbuf + newlen;
mbuf->data_end = newbuf + (mbuf->data_end - mbuf->data);
mbuf->read_pos = newbuf + (mbuf->read_pos - mbuf->data);
mbuf->data = newbuf;
return;
}
int
mbuf_append(MBuf * dst, const uint8 *buf, int len)
{
if (dst->no_write)
{
px_debug("mbuf_append: no_write");
return PXE_BUG;
}
prepare_room(dst, len);
memcpy(dst->data_end, buf, len);
dst->data_end += len;
return 0;
}
MBuf *
mbuf_create(int len)
{
MBuf *mbuf;
if (!len)
len = 8192;
mbuf = px_alloc(sizeof *mbuf);
mbuf->data = px_alloc(len);
mbuf->buf_end = mbuf->data + len;
mbuf->data_end = mbuf->data;
mbuf->read_pos = mbuf->data;
mbuf->no_write = 0;
mbuf->own_data = 1;
return mbuf;
}
MBuf *
mbuf_create_from_data(const uint8 *data, int len)
{
MBuf *mbuf;
mbuf = px_alloc(sizeof *mbuf);
mbuf->data = (uint8 *) data;
mbuf->buf_end = mbuf->data + len;
mbuf->data_end = mbuf->data + len;
mbuf->read_pos = mbuf->data;
mbuf->no_write = 1;
mbuf->own_data = 0;
return mbuf;
}
int
mbuf_grab(MBuf * mbuf, int len, uint8 **data_p)
{
if (len > mbuf_avail(mbuf))
len = mbuf_avail(mbuf);
mbuf->no_write = 1;
*data_p = mbuf->read_pos;
mbuf->read_pos += len;
return len;
}
int mbuf_rewind(MBuf *mbuf)
{
mbuf->read_pos = mbuf->data;
return 0;
}
int
mbuf_steal_data(MBuf * mbuf, uint8 **data_p)
{
int len = mbuf_size(mbuf);
mbuf->no_write = 1;
mbuf->own_data = 0;
*data_p = mbuf->data;
mbuf->data = mbuf->data_end = mbuf->read_pos = mbuf->buf_end = NULL;
return len;
}
/*
* PullFilter
*/
struct PullFilter
{
PullFilter *src;
const PullFilterOps *op;
int buflen;
uint8 *buf;
int pos;
void *priv;
};
int
pullf_create(PullFilter ** pf_p, const PullFilterOps * op, void *init_arg, PullFilter * src)
{
PullFilter *pf;
void *priv;
int res;
if (op->init != NULL)
{
res = op->init(&priv, init_arg, src);
if (res < 0)
return res;
}
else
{
priv = init_arg;
res = 0;
}
pf = px_alloc(sizeof(*pf));
memset(pf, 0, sizeof(*pf));
pf->buflen = res;
pf->op = op;
pf->priv = priv;
pf->src = src;
if (pf->buflen > 0)
{
pf->buf = px_alloc(pf->buflen);
pf->pos = 0;
}
else
{
pf->buf = NULL;
pf->pos = 0;
}
*pf_p = pf;
return 0;
}
void
pullf_free(PullFilter * pf)
{
if (pf->op->free)
pf->op->free(pf->priv);
if (pf->buf)
{
memset(pf->buf, 0, pf->buflen);
px_free(pf->buf);
}
memset(pf, 0, sizeof(*pf));
px_free(pf);
}
/* may return less data than asked, 0 means eof */
int
pullf_read(PullFilter * pf, int len, uint8 **data_p)
{
int res;
if (pf->op->pull)
{
if (pf->buflen && len > pf->buflen)
len = pf->buflen;
res = pf->op->pull(pf->priv, pf->src, len, data_p,
pf->buf, pf->buflen);
}
else
res = pullf_read(pf->src, len, data_p);
return res;
}
int
pullf_read_max(PullFilter * pf, int len, uint8 **data_p, uint8 *tmpbuf)
{
int res, total;
uint8 *tmp;
res = pullf_read(pf, len, data_p);
if (res <= 0 || res == len)
return res;
/* read was shorter, use tmpbuf */
memcpy(tmpbuf, *data_p, res);
*data_p = tmpbuf;
len -= res;
total = res;
while (len > 0) {
res = pullf_read(pf, len, &tmp);
if (res < 0)
{
/* so the caller must clear only on success */
memset(tmpbuf, 0, total);
return res;
}
if (res == 0)
break;
memcpy(tmpbuf + total, tmp, res);
total += res;
}
return total;
}
/*
* caller wants exatly len bytes and dont bother with references
*/
int pullf_read_fixed(PullFilter *src, int len, uint8 *dst)
{
int res;
uint8 *p;
res = pullf_read_max(src, len, &p, dst);
if (res < 0)
return res;
if (res != len)
{
px_debug("pullf_read_fixed: need=%d got=%d", len, res);
return PXE_MBUF_SHORT_READ;
}
if (p != dst)
memcpy(dst, p, len);
return 0;
}
/*
* read from MBuf
*/
static int
pull_from_mbuf(void *arg, PullFilter * src, int len,
uint8 **data_p, uint8 *buf, int buflen)
{
MBuf *mbuf = arg;
return mbuf_grab(mbuf, len, data_p);
}
static const struct PullFilterOps mbuf_reader = {
NULL, pull_from_mbuf, NULL
};
int
pullf_create_mbuf_reader(PullFilter ** mp_p, MBuf * src)
{
return pullf_create(mp_p, &mbuf_reader, src, NULL);
}
/*
* PushFilter
*/
struct PushFilter
{
PushFilter *next;
const PushFilterOps *op;
int block_size;
uint8 *buf;
int pos;
void *priv;
};
int
pushf_create(PushFilter ** mp_p, const PushFilterOps * op, void *init_arg, PushFilter * next)
{
PushFilter *mp;
void *priv;
int res;
if (op->init != NULL)
{
res = op->init(next, init_arg, &priv);
if (res < 0)
return res;
}
else
{
priv = init_arg;
res = 0;
}
mp = px_alloc(sizeof(*mp));
memset(mp, 0, sizeof(*mp));
mp->block_size = res;
mp->op = op;
mp->priv = priv;
mp->next = next;
if (mp->block_size > 0)
{
mp->buf = px_alloc(mp->block_size);
mp->pos = 0;
}
else
{
mp->buf = NULL;
mp->pos = 0;
}
*mp_p = mp;
return 0;
}
void
pushf_free(PushFilter * mp)
{
if (mp->op->free)
mp->op->free(mp->priv);
if (mp->buf)
{
memset(mp->buf, 0, mp->block_size);
px_free(mp->buf);
}
memset(mp, 0, sizeof(*mp));
px_free(mp);
}
void
pushf_free_all(PushFilter * mp)
{
PushFilter *tmp;
while (mp)
{
tmp = mp->next;
pushf_free(mp);
mp = tmp;
}
}
static int
wrap_process(PushFilter * mp, const uint8 *data, int len)
{
int res;
if (mp->op->push != NULL)
res = mp->op->push(mp->next, mp->priv, data, len);
else
res = pushf_write(mp->next, data, len);
if (res > 0)
return PXE_BUG;
return res;
}
/* consumes all data, returns len on success */
int
pushf_write(PushFilter * mp, const uint8 *data, int len)
{
int need,
res;
/*
* no buffering
*/
if (mp->block_size <= 0)
return wrap_process(mp, data, len);
/*
* try to empty buffer
*/
need = mp->block_size - mp->pos;
if (need > 0)
{
if (len < need)
{
memcpy(mp->buf + mp->pos, data, len);
mp->pos += len;
return 0;
}
memcpy(mp->buf + mp->pos, data, need);
len -= need;
data += need;
}
/*
* buffer full, process
*/
res = wrap_process(mp, mp->buf, mp->block_size);
if (res < 0)
return res;
mp->pos = 0;
/*
* now process directly from data
*/
while (len > 0)
{
if (len > mp->block_size)
{
res = wrap_process(mp, data, mp->block_size);
if (res < 0)
return res;
data += mp->block_size;
len -= mp->block_size;
}
else
{
memcpy(mp->buf, data, len);
mp->pos += len;
break;
}
}
return 0;
}
int
pushf_flush(PushFilter * mp)
{
int res;
while (mp)
{
if (mp->block_size > 0)
{
res = wrap_process(mp, mp->buf, mp->pos);
if (res < 0)
return res;
}
if (mp->op->flush)
{
res = mp->op->flush(mp->next, mp->priv);
if (res < 0)
return res;
}
mp = mp->next;
}
return 0;
}
/*
* write to MBuf
*/
static int
push_into_mbuf(PushFilter * next, void *arg, const uint8 *data, int len)
{
int res = 0;
MBuf *mbuf = arg;
if (len > 0)
res = mbuf_append(mbuf, data, len);
return res < 0 ? res : 0;
}
static const struct PushFilterOps mbuf_filter = {
NULL, push_into_mbuf, NULL, NULL
};
int pushf_create_mbuf_writer(PushFilter **res, MBuf *dst)
{
return pushf_create(res, &mbuf_filter, dst, NULL);
}
/*
* mbuf.h
* Memory buffer operations.
*
* Copyright (c) 2005 Marko Kreen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/mbuf.h,v 1.1 2005/07/10 13:46:28 momjian Exp $
*/
#ifndef __PX_MBUF_H
#define __PX_MBUF_H
typedef struct MBuf MBuf;
typedef struct PushFilter PushFilter;
typedef struct PullFilter PullFilter;
typedef struct PushFilterOps PushFilterOps;
typedef struct PullFilterOps PullFilterOps;
struct PushFilterOps
{
/* should return needed buffer size, 0- no buffering, <0 on error
* if NULL, no buffering, and priv=init_arg
*/
int (*init) (PushFilter * next, void *init_arg, void **priv_p);
/* send data to next. should consume all?
* if null, it will be simply copied (in-place)
* returns 0 on error
*/
int (*push) (PushFilter * next, void *priv,
const uint8 *src, int len);
int (*flush) (PushFilter * next, void *priv);
void (*free) (void *priv);
};
struct PullFilterOps
{
/* should return needed buffer size, 0- no buffering, <0 on error
* if NULL, no buffering, and priv=init_arg
*/
int (*init) (void **priv_p, void *init_arg, PullFilter * src);
/* request data from src, put result ptr to data_p
* can use ptr from src or use buf as work area
* if NULL in-place copy
*/
int (*pull) (void *priv, PullFilter * src, int len,
uint8 **data_p, uint8 *buf, int buflen);
void (*free) (void *priv);
};
/*
* Memory buffer
*/
MBuf *mbuf_create(int len);
MBuf *mbuf_create_from_data(const uint8 *data, int len);
int mbuf_tell(MBuf * mbuf);
int mbuf_avail(MBuf * mbuf);
int mbuf_size(MBuf * mbuf);
int mbuf_grab(MBuf * mbuf, int len, uint8 **data_p);
int mbuf_steal_data(MBuf * mbuf, uint8 **data_p);
int mbuf_append(MBuf * dst, const uint8 *buf, int cnt);
int mbuf_rewind(MBuf * mbuf);
int mbuf_free(MBuf * mbuf);
/*
* Push filter
*/
int pushf_create(PushFilter ** res, const PushFilterOps * ops, void *init_arg,
PushFilter * next);
int pushf_write(PushFilter * mp, const uint8 *data, int len);
void pushf_free_all(PushFilter * mp);
void pushf_free(PushFilter * mp);
int pushf_flush(PushFilter * mp);
int pushf_create_mbuf_writer(PushFilter ** mp_p, MBuf * mbuf);
/*
* Pull filter
*/
int pullf_create(PullFilter ** res, const PullFilterOps * ops,
void *init_arg, PullFilter * src);
int pullf_read(PullFilter * mp, int len, uint8 **data_p);
int pullf_read_max(PullFilter * mp, int len,
uint8 **data_p, uint8 *tmpbuf);
void pullf_free(PullFilter * mp);
int pullf_read_fixed(PullFilter *src, int len, uint8 *dst);
int pullf_create_mbuf_reader(PullFilter ** pf_p, MBuf * mbuf);
#define GETBYTE(pf, dst) \
do { \
uint8 __b; \
int __res = pullf_read_fixed(pf, 1, &__b); \
if (__res < 0) \
return __res; \
(dst) = __b; \
} while (0)
#endif /* __PX_MBUF_H */
/*
* pgp-armor.c
* PGP ascii-armor.
*
* Copyright (c) 2005 Marko Kreen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-armor.c,v 1.1 2005/07/10 13:46:28 momjian Exp $
*/
#include <postgres.h>
#include <string.h>
#include "px.h"
#include "mbuf.h"
#include "pgp.h"
/*
* BASE64 - duplicated :(
*/
static const unsigned char _base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static int
b64_encode(const uint8 *src, unsigned len, uint8 *dst)
{
uint8 *p,
*lend = dst + 76;
const uint8 *s,
*end = src + len;
int pos = 2;
unsigned long buf = 0;
s = src;
p = dst;
while (s < end)
{
buf |= *s << (pos << 3);
pos--;
s++;
/*
* write it out
*/
if (pos < 0)
{
*p++ = _base64[(buf >> 18) & 0x3f];
*p++ = _base64[(buf >> 12) & 0x3f];
*p++ = _base64[(buf >> 6) & 0x3f];
*p++ = _base64[buf & 0x3f];
pos = 2;
buf = 0;
}
if (p >= lend)
{
*p++ = '\n';
lend = p + 76;
}
}
if (pos != 2)
{
*p++ = _base64[(buf >> 18) & 0x3f];
*p++ = _base64[(buf >> 12) & 0x3f];
*p++ = (pos == 0) ? _base64[(buf >> 6) & 0x3f] : '=';
*p++ = '=';
}
return p - dst;
}
/* probably should use lookup table */
static int
b64_decode(const uint8 *src, unsigned len, uint8 *dst)
{
const uint8 *srcend = src + len,
*s = src;
uint8 *p = dst;
char c;
unsigned b = 0;
unsigned long buf = 0;
int pos = 0,
end = 0;
while (s < srcend)
{
c = *s++;
if (c >= 'A' && c <= 'Z')
b = c - 'A';
else if (c >= 'a' && c <= 'z')
b = c - 'a' + 26;
else if (c >= '0' && c <= '9')
b = c - '0' + 52;
else if (c == '+')
b = 62;
else if (c == '/')
b = 63;
else if (c == '=')
{
/*
* end sequence
*/
if (!end)
{
if (pos == 2)
end = 1;
else if (pos == 3)
end = 2;
else
return PXE_PGP_CORRUPT_ARMOR;
}
b = 0;
}
else if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
continue;
else
return PXE_PGP_CORRUPT_ARMOR;
/*
* add it to buffer
*/
buf = (buf << 6) + b;
pos++;
if (pos == 4)
{
*p++ = (buf >> 16) & 255;
if (end == 0 || end > 1)
*p++ = (buf >> 8) & 255;
if (end == 0 || end > 2)
*p++ = buf & 255;
buf = 0;
pos = 0;
}
}
if (pos != 0)
return PXE_PGP_CORRUPT_ARMOR;
return p - dst;
}
static unsigned
b64_enc_len(unsigned srclen)
{
/*
* 3 bytes will be converted to 4, linefeed after 76 chars
*/
return (srclen + 2) * 4 / 3 + srclen / (76 * 3 / 4);
}
static unsigned
b64_dec_len(unsigned srclen)
{
return (srclen * 3) >> 2;
}
/*
* PGP armor
*/
static const char *armor_header = "-----BEGIN PGP MESSAGE-----\n\n";
static const char *armor_footer = "\n-----END PGP MESSAGE-----\n";
/* CRC24 implementation from rfc2440 */
#define CRC24_INIT 0x00b704ceL
#define CRC24_POLY 0x01864cfbL
static long
crc24(const uint8 *data, unsigned len)
{
unsigned crc = CRC24_INIT;
int i;
while (len--)
{
crc ^= (*data++) << 16;
for (i = 0; i < 8; i++)
{
crc <<= 1;
if (crc & 0x1000000)
crc ^= CRC24_POLY;
}
}
return crc & 0xffffffL;
}
int
pgp_armor_encode(const uint8 *src, unsigned len, uint8 *dst)
{
int n;
uint8 *pos = dst;
unsigned crc = crc24(src, len);
n = strlen(armor_header);
memcpy(pos, armor_header, n);
pos += n;
n = b64_encode(src, len, pos);
pos += n;
if (*(pos - 1) != '\n')
*pos++ = '\n';
*pos++ = '=';
pos[3] = _base64[crc & 0x3f];
crc >>= 6;
pos[2] = _base64[crc & 0x3f];
crc >>= 6;
pos[1] = _base64[crc & 0x3f];
crc >>= 6;
pos[0] = _base64[crc & 0x3f];
pos += 4;
n = strlen(armor_footer);
memcpy(pos, armor_footer, n);
pos += n;
return pos - dst;
}
static const uint8 *
find_str(const uint8 *data, const uint8 *data_end, const char *str, int strlen)
{
const uint8 *p = data;
if (!strlen)
return NULL;
if (data_end - data < strlen)
return NULL;
while (p < data_end) {
p = memchr(p, str[0], data_end - p);
if (p == NULL)
return NULL;
if (p + strlen > data_end)
return NULL;
if (memcmp(p, str, strlen) == 0)
return p;
p++;
}
return NULL;
}
static int
find_header(const uint8 *data, const uint8 *datend,
const uint8 **start_p, int is_end)
{
const uint8 *p = data;
static const char *start_sep = "-----BEGIN";
static const char *end_sep = "-----END";
const char *sep = is_end ? end_sep : start_sep;
/* find header line */
while (1)
{
p = find_str(p, datend, sep, strlen(sep));
if (p == NULL)
return PXE_PGP_CORRUPT_ARMOR;
/* it must start at beginning of line */
if (p == data || *(p - 1) == '\n')
break;
p += strlen(sep);
}
*start_p = p;
p += strlen(sep);
/* check if header text ok */
for (; p < datend && *p != '-'; p++)
{
/* various junk can be there, but definitely not line-feed */
if (*p >= ' ')
continue;
return PXE_PGP_CORRUPT_ARMOR;
}
if (datend - p < 5 || memcmp(p, sep, 5) != 0)
return PXE_PGP_CORRUPT_ARMOR;
p += 5;
/* check if at end of line */
if (p < datend)
{
if (*p != '\n' && *p != '\r')
return PXE_PGP_CORRUPT_ARMOR;
if (*p == '\r')
p++;
if (p < datend && *p == '\n')
p++;
}
return p - *start_p;
}
int
pgp_armor_decode(const uint8 *src, unsigned len, uint8 *dst)
{
const uint8 *p = src;
const uint8 *data_end = src + len;
long crc;
const uint8 *base64_start, *armor_end;
const uint8 *base64_end = NULL;
uint8 buf[4];
int hlen;
int res = PXE_PGP_CORRUPT_ARMOR;
/* armor start */
hlen = find_header(src, data_end, &p, 0);
if (hlen <= 0)
goto out;
p += hlen;
/* armor end */
hlen = find_header(p, data_end, &armor_end, 1);
if (hlen <= 0)
goto out;
/* skip comments - find empty line */
while (p < armor_end && *p != '\n' && *p != '\r')
{
p = memchr(p, '\n', armor_end - p);
if (!p)
goto out;
/* step to start of next line */
p++;
}
base64_start = p;
/* find crc pos */
for (p = armor_end; p >= base64_start; p--)
if (*p == '=')
{
base64_end = p - 1;
break;
}
if (base64_end == NULL)
goto out;
/* decode crc */
if (b64_decode(p + 1, 4, buf) != 3)
goto out;
crc = (((long)buf[0]) << 16) + (((long)buf[1]) << 8) + (long)buf[2];
/* decode data */
res = b64_decode(base64_start, base64_end - base64_start, dst);
/* check crc */
if (res >= 0 && crc24(dst, res) != crc)
res = PXE_PGP_CORRUPT_ARMOR;
out:
return res;
}
unsigned
pgp_armor_enc_len(unsigned len)
{
return b64_enc_len(len) + strlen(armor_header) + strlen(armor_footer) + 16;
}
unsigned
pgp_armor_dec_len(unsigned len)
{
return b64_dec_len(len);
}
/*
* pgp-cfb.c
* Implements both normal and PGP-specific CFB mode.
*
* Copyright (c) 2005 Marko Kreen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-cfb.c,v 1.1 2005/07/10 13:46:28 momjian Exp $
*/
#include <postgres.h>
#include "mbuf.h"
#include "px.h"
#include "pgp.h"
typedef int (*mix_data_t)(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst);
struct PGP_CFB
{
PX_Cipher *ciph;
int block_size;
int pos;
int block_no;
int resync;
uint8 fr[PGP_MAX_BLOCK];
uint8 fre[PGP_MAX_BLOCK];
uint8 encbuf[PGP_MAX_BLOCK];
};
int
pgp_cfb_create(PGP_CFB **ctx_p, int algo, const uint8 *key, int key_len,
int resync, uint8 *iv)
{
int res;
PX_Cipher *ciph;
PGP_CFB *ctx;
res = pgp_load_cipher(algo, &ciph);
if (res < 0)
return res;
res = px_cipher_init(ciph, key, key_len, NULL);
if (res < 0)
{
px_cipher_free(ciph);
return res;
}
ctx = px_alloc(sizeof(*ctx));
memset(ctx, 0, sizeof(*ctx));
ctx->ciph = ciph;
ctx->block_size = px_cipher_block_size(ciph);
ctx->resync = resync;
if (iv)
memcpy(ctx->fr, iv, ctx->block_size);
*ctx_p = ctx;
return 0;
}
void
pgp_cfb_free(PGP_CFB *ctx)
{
px_cipher_free(ctx->ciph);
memset(ctx, 0, sizeof(*ctx));
px_free(ctx);
}
/*
* Data processing for normal CFB. (PGP_PKT_SYMENCRYPTED_DATA_MDC)
*/
static int
mix_encrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
{
int i;
for (i = ctx->pos; i < ctx->pos + len; i++)
*dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
ctx->pos += len;
return len;
}
static int
mix_decrypt_normal(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
{
int i;
for (i = ctx->pos; i < ctx->pos + len; i++)
{
ctx->encbuf[i] = *data++;
*dst++ = ctx->fre[i] ^ ctx->encbuf[i];
}
ctx->pos += len;
return len;
}
/*
* Data processing for old PGP CFB mode. (PGP_PKT_SYMENCRYPTED_DATA)
*
* The goal is to hide the horror from the rest of the code,
* thus its all concentrated here.
*/
static int
mix_encrypt_resync(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
{
int i,n;
/* block #2 is 2 bytes long */
if (ctx->block_no == 2)
{
n = 2 - ctx->pos;
if (len < n)
n = len;
for (i = ctx->pos; i < ctx->pos + n; i++)
*dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
ctx->pos += n;
len -= n;
if (ctx->pos == 2)
{
memcpy(ctx->fr, ctx->encbuf + 2, ctx->block_size - 2);
memcpy(ctx->fr + ctx->block_size - 2, ctx->encbuf, 2);
ctx->pos = 0;
return n;
}
}
for (i = ctx->pos; i < ctx->pos + len; i++)
*dst++ = ctx->encbuf[i] = ctx->fre[i] ^ (*data++);
ctx->pos += len;
return len;
}
static int
mix_decrypt_resync(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
{
int i,n;
/* block #2 is 2 bytes long */
if (ctx->block_no == 2)
{
n = 2 - ctx->pos;
if (len < n)
n = len;
for (i = ctx->pos; i < ctx->pos + n; i++)
{
ctx->encbuf[i] = *data++;
*dst++ = ctx->fre[i] ^ ctx->encbuf[i];
}
ctx->pos += n;
len -= n;
if (ctx->pos == 2)
{
memcpy(ctx->fr, ctx->encbuf + 2, ctx->block_size - 2);
memcpy(ctx->fr + ctx->block_size - 2, ctx->encbuf, 2);
ctx->pos = 0;
return n;
}
}
for (i = ctx->pos; i < ctx->pos + len; i++)
{
ctx->encbuf[i] = *data++;
*dst++ = ctx->fre[i] ^ ctx->encbuf[i];
}
ctx->pos += len;
return len;
}
/*
* common code for both encrypt and decrypt.
*/
static int
cfb_process(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst,
mix_data_t mix_data)
{
int n;
int res;
while (len > 0 && ctx->pos > 0)
{
n = ctx->block_size - ctx->pos;
if (len < n)
n = len;
n = mix_data(ctx, data, n, dst);
data += n;
dst += n;
len -= n;
if (ctx->pos == ctx->block_size)
{
memcpy(ctx->fr, ctx->encbuf, ctx->block_size);
ctx->pos = 0;
}
}
while (len > 0)
{
px_cipher_encrypt(ctx->ciph, ctx->fr, ctx->block_size, ctx->fre);
if (ctx->block_no < 5)
ctx->block_no++;
n = ctx->block_size;
if (len < n)
n = len;
res = mix_data(ctx, data, n, dst);
data += res;
dst += res;
len -= res;
if (ctx->pos == ctx->block_size)
{
memcpy(ctx->fr, ctx->encbuf, ctx->block_size);
ctx->pos = 0;
}
}
return 0;
}
/*
* public interface
*/
int
pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
{
mix_data_t mix = ctx->resync ? mix_encrypt_resync : mix_encrypt_normal;
return cfb_process(ctx, data, len, dst, mix);
}
int
pgp_cfb_decrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
{
mix_data_t mix = ctx->resync ? mix_decrypt_resync : mix_decrypt_normal;
return cfb_process(ctx, data, len, dst, mix);
}
/*
* pgp-compress.c
* ZIP and ZLIB compression via zlib.
*
* Copyright (c) 2005 Marko Kreen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-compress.c,v 1.1 2005/07/10 13:46:28 momjian Exp $
*/
#include <postgres.h>
#include "mbuf.h"
#include "px.h"
#include "pgp.h"
/*
* Compressed pkt writer
*/
#ifndef DISABLE_ZLIB
#include <zlib.h>
#define ZIP_OUT_BUF 8192
#define ZIP_IN_BLOCK 8192
struct ZipStat
{
uint8 type;
int buf_len;
int hdr_done;
z_stream stream;
uint8 buf[ZIP_OUT_BUF];
};
static void *
z_alloc(void *priv, unsigned n_items, unsigned item_len)
{
return px_alloc(n_items * item_len);
}
static void
z_free(void *priv, void *addr)
{
px_free(addr);
}
static int
compress_init(PushFilter * next, void *init_arg, void **priv_p)
{
int res;
struct ZipStat *st;
PGP_Context *ctx = init_arg;
uint8 type = ctx->compress_algo;
if (type != PGP_COMPR_ZLIB && type != PGP_COMPR_ZIP)
return PXE_PGP_UNSUPPORTED_COMPR;
/*
* init
*/
st = px_alloc(sizeof(*st));
memset(st, 0, sizeof(*st));
st->buf_len = ZIP_OUT_BUF;
st->stream.zalloc = z_alloc;
st->stream.zfree = z_free;
if (type == PGP_COMPR_ZIP)
res = deflateInit2(&st->stream, ctx->compress_level,
Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
else
res = deflateInit(&st->stream, ctx->compress_level);
if (res != Z_OK)
{
px_free(st);
return PXE_PGP_COMPRESSION_ERROR;
}
*priv_p = st;
return ZIP_IN_BLOCK;
}
/* writes compressed data packet */
/* cant handle zero-len incoming data, but shouldnt */
static int
compress_process(PushFilter * next, void *priv, const uint8 *data, int len)
{
int res,
n_out;
struct ZipStat *st = priv;
/*
* process data
*/
while (len > 0)
{
st->stream.next_in = (void *) data;
st->stream.avail_in = len;
st->stream.next_out = st->buf;
st->stream.avail_out = st->buf_len;
res = deflate(&st->stream, 0);
if (res != Z_OK)
return PXE_PGP_COMPRESSION_ERROR;
n_out = st->buf_len - st->stream.avail_out;
if (n_out > 0)
{
res = pushf_write(next, st->buf, n_out);
if (res < 0)
return res;
}
len = st->stream.avail_in;
}
return 0;
}
static int
compress_flush(PushFilter * next, void *priv)
{
int res,
zres,
n_out;
struct ZipStat *st = priv;
st->stream.next_in = NULL;
st->stream.avail_in = 0;
while (1)
{
st->stream.next_out = st->buf;
st->stream.avail_out = st->buf_len;
zres = deflate(&st->stream, Z_FINISH);
if (zres != Z_STREAM_END && zres != Z_OK)
return PXE_PGP_COMPRESSION_ERROR;
n_out = st->buf_len - st->stream.avail_out;
if (n_out > 0)
{
res = pushf_write(next, st->buf, n_out);
if (res < 0)
return res;
}
if (zres == Z_STREAM_END)
break;
}
return 0;
}
static void
compress_free(void *priv)
{
struct ZipStat *st = priv;
deflateEnd(&st->stream);
memset(st, 0, sizeof(*st));
px_free(st);
}
static const PushFilterOps
compress_filter = {
compress_init, compress_process, compress_flush, compress_free
};
int
pgp_compress_filter(PushFilter **res, PGP_Context *ctx, PushFilter *dst)
{
return pushf_create(res, &compress_filter, ctx, dst);
}
/*
* Decompress
*/
struct DecomprData
{
int buf_len; /* = ZIP_OUT_BUF */
int buf_data; /* available data */
uint8 *pos;
z_stream stream;
int eof;
uint8 buf[ZIP_OUT_BUF];
};
static int
decompress_init(void **priv_p, void *arg, PullFilter *src)
{
PGP_Context *ctx = arg;
struct DecomprData *dec;
int res;
if (ctx->compress_algo != PGP_COMPR_ZLIB
&& ctx->compress_algo != PGP_COMPR_ZIP)
return PXE_PGP_UNSUPPORTED_COMPR;
dec = px_alloc(sizeof(*dec));
memset(dec, 0, sizeof(*dec));
dec->buf_len = ZIP_OUT_BUF;
*priv_p = dec;
dec->stream.zalloc = z_alloc;
dec->stream.zfree = z_free;
if (ctx->compress_algo == PGP_COMPR_ZIP)
res = inflateInit2(&dec->stream, -15);
else
res = inflateInit(&dec->stream);
if (res != Z_OK)
{
px_free(dec);
px_debug("decompress_init: inflateInit error");
return PXE_PGP_COMPRESSION_ERROR;
}
return 0;
}
static int decompress_read(void *priv, PullFilter *src, int len,
uint8 **data_p, uint8 *buf, int buflen)
{
int res;
int flush;
struct DecomprData *dec = priv;
restart:
if (dec->buf_data > 0)
{
if (len > dec->buf_data)
len = dec->buf_data;
*data_p = dec->pos;
dec->pos += len;
dec->buf_data -= len;
return len;
}
if (dec->eof)
return 0;
if (dec->stream.avail_in == 0) {
uint8 *tmp;
res = pullf_read(src, 8192, &tmp);
if (res < 0)
return res;
dec->stream.next_in = tmp;
dec->stream.avail_in = res;
}
dec->stream.next_out = dec->buf;
dec->stream.avail_out = dec->buf_len;
dec->pos = dec->buf;
// Z_NO_FLUSH, Z_SYNC_FLUSH,
flush = dec->stream.avail_in ? Z_SYNC_FLUSH : Z_FINISH;
res = inflate(&dec->stream, flush);
if (res != Z_OK && res != Z_STREAM_END)
{
px_debug("decompress_read: inflate error: %d", res);
return PXE_PGP_CORRUPT_DATA;
}
dec->buf_data = dec->buf_len - dec->stream.avail_out;
if (res == Z_STREAM_END)
dec->eof = 1;
goto restart;
}
static void decompress_free(void *priv)
{
struct DecomprData *dec = priv;
inflateEnd(&dec->stream);
memset(dec, 0, sizeof(*dec));
px_free(dec);
}
static const PullFilterOps
decompress_filter = {
decompress_init, decompress_read, decompress_free
};
int
pgp_decompress_filter(PullFilter **res, PGP_Context *ctx, PullFilter *src)
{
return pullf_create(res, &decompress_filter, ctx, src);
}
#else /* DISABLE_ZLIB */
int
pgp_compress_filter(PushFilter **res, PGP_Context *ctx, PushFilter *dst)
{
return PXE_PGP_UNSUPPORTED_COMPR;
}
int
pgp_decompress_filter(PullFilter **res, PGP_Context *ctx, PullFilter *src)
{
return PXE_PGP_UNSUPPORTED_COMPR;
}
#endif
此差异已折叠。
此差异已折叠。
/*
* pgp-info.c
* Provide info about PGP data.
*
* Copyright (c) 2005 Marko Kreen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-info.c,v 1.1 2005/07/10 13:46:28 momjian Exp $
*/
#include <postgres.h>
#include "px.h"
#include "mbuf.h"
#include "pgp.h"
static int read_pubkey_keyid(PullFilter *pkt, uint8 *keyid_buf)
{
int res = 0;
PGP_PubKey *pk;
res = pgp_key_alloc(&pk);
if (res < 0)
return res;
res = _pgp_read_public_key(pkt, pk);
if (res < 0)
goto err;
res = pgp_skip_packet(pkt);
if (res < 0)
goto err;
res = 0;
if (pk->algo == PGP_PUB_ELG_ENCRYPT)
{
memcpy(keyid_buf, pk->key_id, 8);
res = 1;
}
err:
pgp_key_free(pk);
return res;
}
static int read_pubenc_keyid(PullFilter *pkt, uint8 *keyid_buf)
{
uint8 ver;
int res;
GETBYTE(pkt, ver);
if (ver != 3)
return -1;
res = pullf_read_fixed(pkt, 8, keyid_buf);
if (res < 0)
return res;
return pgp_skip_packet(pkt);
}
static const char hextbl[] = "0123456789ABCDEF";
static int
print_key(uint8 *keyid, char *dst)
{
int i;
unsigned c;
for (i = 0; i < 8; i++) {
c = keyid[i];
*dst++ = hextbl[(c >> 4) & 0x0F];
*dst++ = hextbl[c & 0x0F];
}
*dst = 0;
return 8*2;
}
static const uint8 any_key[] =
{ 0, 0, 0, 0, 0, 0, 0, 0 };
/*
* dst should have room for 17 bytes
*/
int
pgp_get_keyid(MBuf *pgp_data, char *dst)
{
int res;
PullFilter *src;
PullFilter *pkt = NULL;
int len;
uint8 tag;
int got_pub_key=0, got_symenc_key=0, got_pubenc_key=0;
int got_data=0;
uint8 keyid_buf[8];
res = pullf_create_mbuf_reader(&src, pgp_data);
if (res < 0)
return res;
while (1) {
res = pgp_parse_pkt_hdr(src, &tag, &len, 0);
if (res <= 0)
break;
res = pgp_create_pkt_reader(&pkt, src, len, res, NULL);
if (res < 0)
break;
switch (tag)
{
case PGP_PKT_SECRET_KEY:
case PGP_PKT_PUBLIC_KEY:
case PGP_PKT_SECRET_SUBKEY:
case PGP_PKT_PUBLIC_SUBKEY:
res = read_pubkey_keyid(pkt, keyid_buf);
if (res < 0)
break;
if (res > 0)
got_pub_key++;
break;
case PGP_PKT_PUBENCRYPTED_SESSKEY:
got_pubenc_key++;
res = read_pubenc_keyid(pkt, keyid_buf);
break;
case PGP_PKT_SYMENCRYPTED_DATA:
case PGP_PKT_SYMENCRYPTED_DATA_MDC:
got_data = 1;
break;
case PGP_PKT_SYMENCRYPTED_SESSKEY:
got_symenc_key++;
/* fallthru */
case PGP_PKT_SIGNATURE:
case PGP_PKT_MARKER:
case PGP_PKT_TRUST:
case PGP_PKT_USER_ID:
case PGP_PKT_USER_ATTR:
case PGP_PKT_PRIV_61:
res = pgp_skip_packet(pkt);
break;
default:
res = PXE_PGP_CORRUPT_DATA;
}
if (pkt)
pullf_free(pkt);
pkt = NULL;
if (res < 0 || got_data)
break;
}
pullf_free(src);
if (pkt)
pullf_free(pkt);
if (res < 0)
return res;
/* now check sanity */
if (got_pub_key && got_pubenc_key)
res = PXE_PGP_CORRUPT_DATA;
if (got_pub_key > 1)
res = -1;
if (got_pubenc_key > 1)
res = -1;
/*
* if still ok, look what we got
*/
if (res >= 0)
{
if (got_pubenc_key || got_pub_key)
{
if (memcmp(keyid_buf, any_key, 8) == 0)
{
memcpy(dst, "ANYKEY", 7);
res = 6;
}
else
res = print_key(keyid_buf, dst);
}
else if (got_symenc_key)
{
memcpy(dst, "SYMKEY", 7);
res = 6;
}
else
res = PXE_PGP_NO_USABLE_KEY;
}
return res;
}
/*
* pgp-mpi-internal.c
* OpenPGP MPI functions.
*
* Copyright (c) 2005 Marko Kreen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi-internal.c,v 1.1 2005/07/10 13:46:28 momjian Exp $
*/
#include <postgres.h>
#include "px.h"
#include "mbuf.h"
#include "pgp.h"
int
pgp_elgamal_encrypt(PGP_PubKey *pk, PGP_MPI *_m,
PGP_MPI **c1_p, PGP_MPI **c2_p)
{
return PXE_PGP_NO_BIGNUM;
}
int
pgp_elgamal_decrypt(PGP_PubKey *pk, PGP_MPI *_c1, PGP_MPI *_c2,
PGP_MPI **msg_p)
{
return PXE_PGP_NO_BIGNUM;
}
此差异已折叠。
/*
* pgp-mpi.c
* OpenPGP MPI helper functions.
*
* Copyright (c) 2005 Marko Kreen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi.c,v 1.1 2005/07/10 13:46:29 momjian Exp $
*/
#include <postgres.h>
#include "px.h"
#include "mbuf.h"
#include "pgp.h"
int pgp_mpi_alloc(int bits, PGP_MPI **mpi)
{
PGP_MPI *n;
int len = (bits + 7) / 8;
if (bits < 0 || bits > 0xFFFF)
{
px_debug("pgp_mpi_alloc: unreasonable request: bits=%d", bits);
return PXE_PGP_CORRUPT_DATA;
}
n = px_alloc(sizeof(*n) + len);
n->bits = bits;
n->bytes = len;
n->data = (uint8*)(n) + sizeof(*n);
*mpi = n;
return 0;
}
int pgp_mpi_create(uint8 *data, int bits, PGP_MPI **mpi)
{
int res;
PGP_MPI *n;
res = pgp_mpi_alloc(bits, &n);
if (res < 0)
return res;
memcpy(n->data, data, n->bytes);
*mpi = n;
return 0;
}
int pgp_mpi_free(PGP_MPI *mpi)
{
memset(mpi, 0, sizeof(*mpi) + mpi->bytes);
px_free(mpi);
return 0;
}
int pgp_mpi_read(PullFilter *src, PGP_MPI **mpi)
{
int res;
uint8 hdr[2];
int bits;
PGP_MPI *n;
res = pullf_read_fixed(src, 2, hdr);
if (res < 0)
return res;
bits = ((unsigned)hdr[0] << 8) + hdr[1];
res = pgp_mpi_alloc(bits, &n);
if (res < 0)
return res;
res = pullf_read_fixed(src, n->bytes, n->data);
if (res < 0)
pgp_mpi_free(n);
else
*mpi = n;
return res;
}
int pgp_mpi_write(PushFilter *dst, PGP_MPI *n)
{
int res;
uint8 buf[2];
buf[0] = n->bits >> 8;
buf[1] = n->bits & 0xFF;
res = pushf_write(dst, buf, 2);
if (res >= 0)
res = pushf_write(dst, n->data, n->bytes);
return res;
}
int pgp_mpi_hash(PX_MD *md, PGP_MPI *n)
{
uint8 buf[2];
buf[0] = n->bits >> 8;
buf[1] = n->bits & 0xFF;
px_md_update(md, buf, 2);
px_md_update(md, n->data, n->bytes);
return 0;
}
unsigned pgp_mpi_cksum(unsigned cksum, PGP_MPI *n)
{
int i;
cksum += n->bits >> 8;
cksum += n->bits & 0xFF;
for (i = 0; i < n->bytes; i++)
cksum += n->data[i];
return cksum;
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册