Commit e94dd6ab authored by Bruce Momjian's avatar Bruce Momjian

Add missing pgcrypto files from previous commit.

parent 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)
This diff is collapsed.
--
-- 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
This diff is collapsed.
This diff is collapsed.
/*
* 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;
}
This diff is collapsed.
/*
* 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;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment