1073 lines
30 KiB
Diff
1073 lines
30 KiB
Diff
|
diff --git a/config.h.cmake b/config.h.cmake
|
||
|
index 7989cbfb..6f5e147e 100644
|
||
|
--- a/config.h.cmake
|
||
|
+++ b/config.h.cmake
|
||
|
@@ -24,9 +24,6 @@
|
||
|
/* Use zlib instead of builtin zlib decoder to uncompress flate streams. */
|
||
|
#cmakedefine ENABLE_ZLIB_UNCOMPRESS 1
|
||
|
|
||
|
-/* Build against libnss3 for digital signature validation */
|
||
|
-#cmakedefine ENABLE_NSS3 1
|
||
|
-
|
||
|
/* Use cairo for rendering. */
|
||
|
#cmakedefine HAVE_CAIRO 1
|
||
|
|
||
|
diff --git a/poppler/Decrypt.cc b/poppler/Decrypt.cc
|
||
|
index 16476f4f..9f4adda3 100644
|
||
|
--- a/poppler/Decrypt.cc
|
||
|
+++ b/poppler/Decrypt.cc
|
||
|
@@ -39,17 +39,33 @@
|
||
|
#include "goo/grandom.h"
|
||
|
#include "Decrypt.h"
|
||
|
#include "Error.h"
|
||
|
-
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+#include <nss.h>
|
||
|
+#include <prerror.h>
|
||
|
+#include <sechash.h>
|
||
|
+#endif
|
||
|
+
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+static PK11Context *rc4InitContext(const Guchar *key, int keyLen);
|
||
|
+static Guchar rc4DecryptByte(PK11Context *context, Guchar c);
|
||
|
+#else
|
||
|
static void rc4InitKey(Guchar *key, int keyLen, Guchar *state);
|
||
|
static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c);
|
||
|
+#endif
|
||
|
|
||
|
static GBool aesReadBlock(Stream *str, Guchar *in, GBool addPadding);
|
||
|
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+static PK11Context *aesInitContext(Guchar *in, Guchar *objKey, int objKeyLength, GBool decrypt);
|
||
|
+#else
|
||
|
static void aesKeyExpansion(DecryptAESState *s, Guchar *objKey, int objKeyLen, GBool decrypt);
|
||
|
+#endif
|
||
|
static void aesEncryptBlock(DecryptAESState *s, Guchar *in);
|
||
|
static void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last);
|
||
|
|
||
|
+#ifndef ENABLE_NSS3
|
||
|
static void aes256KeyExpansion(DecryptAES256State *s, Guchar *objKey, int objKeyLen, GBool decrypt);
|
||
|
+#endif
|
||
|
static void aes256EncryptBlock(DecryptAES256State *s, Guchar *in);
|
||
|
static void aes256DecryptBlock(DecryptAES256State *s, Guchar *in, GBool last);
|
||
|
|
||
|
@@ -70,6 +86,31 @@ static const Guchar passwordPad[32] = {
|
||
|
// Decrypt
|
||
|
//------------------------------------------------------------------------
|
||
|
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+static void shutdownNSS()
|
||
|
+{
|
||
|
+ if (NSS_Shutdown() != SECSuccess) {
|
||
|
+ error(errInternal, -1, "NSS shutdown failed: {0:s}",
|
||
|
+ PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static GBool initNSS() {
|
||
|
+ if (NSS_IsInitialized()) {
|
||
|
+ return gTrue;
|
||
|
+ } else {
|
||
|
+ if (NSS_NoDB_Init(".") != SECSuccess) {
|
||
|
+ error(errInternal, -1, "NSS initialization failed: {0:s}",
|
||
|
+ PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
|
||
|
+ return gFalse;
|
||
|
+ } else {
|
||
|
+ atexit(shutdownNSS);
|
||
|
+ return gTrue;
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+#endif
|
||
|
+
|
||
|
GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength,
|
||
|
GooString *ownerKey, GooString *userKey,
|
||
|
GooString *ownerEnc, GooString *userEnc,
|
||
|
@@ -80,13 +121,21 @@ GBool Decrypt::makeFileKey(int encVersio
|
||
|
DecryptAES256State state;
|
||
|
Guchar test[127 + 56], test2[32];
|
||
|
GooString *userPassword2;
|
||
|
- Guchar fState[256];
|
||
|
Guchar tmpKey[16];
|
||
|
- Guchar fx, fy;
|
||
|
int len, i, j;
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ PK11Context *rc4Context;
|
||
|
+#else
|
||
|
+ Guchar fState[256];
|
||
|
+ Guchar fx, fy;
|
||
|
+#endif
|
||
|
|
||
|
*ownerPasswordOk = gFalse;
|
||
|
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ initNSS();
|
||
|
+#endif
|
||
|
+
|
||
|
if (encRevision == 5 || encRevision == 6) {
|
||
|
|
||
|
// check the owner password
|
||
|
@@ -115,15 +164,27 @@ GBool Decrypt::makeFileKey(int encVersio
|
||
|
//test contains the initial SHA-256 hash input K.
|
||
|
revision6Hash(ownerPassword, test, userKey->getCString());
|
||
|
}
|
||
|
+#ifndef ENABLE_NSS3
|
||
|
aes256KeyExpansion(&state, test, 32, gTrue);
|
||
|
+#endif
|
||
|
for (i = 0; i < 16; ++i) {
|
||
|
state.cbc[i] = 0;
|
||
|
}
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ state.context = aesInitContext(state.cbc, test, 32, gTrue);
|
||
|
+ if (state.context) {
|
||
|
+#endif
|
||
|
aes256DecryptBlock(&state, (Guchar *)ownerEnc->getCString(), gFalse);
|
||
|
memcpy(fileKey, state.buf, 16);
|
||
|
aes256DecryptBlock(&state, (Guchar *)ownerEnc->getCString() + 16,
|
||
|
gFalse);
|
||
|
memcpy(fileKey + 16, state.buf, 16);
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ PK11_DestroyContext(state.context, PR_TRUE);
|
||
|
+ } else {
|
||
|
+ return gFalse;
|
||
|
+ }
|
||
|
+#endif
|
||
|
|
||
|
*ownerPasswordOk = gTrue;
|
||
|
return gTrue;
|
||
|
@@ -156,15 +217,27 @@ GBool Decrypt::makeFileKey(int encVersio
|
||
|
//user key is not used in computing intermediate user key.
|
||
|
revision6Hash(userPassword, test, nullptr);
|
||
|
}
|
||
|
+#ifndef ENABLE_NSS3
|
||
|
aes256KeyExpansion(&state, test, 32, gTrue);
|
||
|
+#endif
|
||
|
for (i = 0; i < 16; ++i) {
|
||
|
state.cbc[i] = 0;
|
||
|
}
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ state.context = aesInitContext(state.cbc, test, 32, gTrue);
|
||
|
+ if (state.context) {
|
||
|
+#endif
|
||
|
aes256DecryptBlock(&state, (Guchar *)userEnc->getCString(), gFalse);
|
||
|
memcpy(fileKey, state.buf, 16);
|
||
|
aes256DecryptBlock(&state, (Guchar *)userEnc->getCString() + 16,
|
||
|
gFalse);
|
||
|
memcpy(fileKey + 16, state.buf, 16);
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ PK11_DestroyContext(state.context, PR_TRUE);
|
||
|
+ } else {
|
||
|
+ return gFalse;
|
||
|
+ }
|
||
|
+#endif
|
||
|
|
||
|
return gTrue;
|
||
|
}
|
||
|
@@ -189,22 +262,41 @@ GBool Decrypt::makeFileKey(int encVersio
|
||
|
}
|
||
|
}
|
||
|
if (encRevision == 2) {
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ rc4Context = rc4InitContext(test, keyLength);
|
||
|
+ if (rc4Context) {
|
||
|
+ for (i = 0; i < 32; ++i)
|
||
|
+ test2[i] = rc4DecryptByte(rc4Context, ownerKey->getChar(i));
|
||
|
+ PK11_DestroyContext(rc4Context, PR_TRUE);
|
||
|
+ }
|
||
|
+#else
|
||
|
rc4InitKey(test, keyLength, fState);
|
||
|
fx = fy = 0;
|
||
|
for (i = 0; i < 32; ++i) {
|
||
|
test2[i] = rc4DecryptByte(fState, &fx, &fy, ownerKey->getChar(i));
|
||
|
}
|
||
|
+#endif
|
||
|
} else {
|
||
|
memcpy(test2, ownerKey->getCString(), 32);
|
||
|
for (i = 19; i >= 0; --i) {
|
||
|
for (j = 0; j < keyLength; ++j) {
|
||
|
tmpKey[j] = test[j] ^ i;
|
||
|
}
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ rc4Context = rc4InitContext(tmpKey, keyLength);
|
||
|
+ if (rc4Context) {
|
||
|
+ for (j = 0; j < 32; ++j) {
|
||
|
+ test2[j] = rc4DecryptByte(rc4Context, test2[j]);
|
||
|
+ }
|
||
|
+ PK11_DestroyContext(rc4Context, PR_TRUE);
|
||
|
+ }
|
||
|
+#else
|
||
|
rc4InitKey(tmpKey, keyLength, fState);
|
||
|
fx = fy = 0;
|
||
|
for (j = 0; j < 32; ++j) {
|
||
|
test2[j] = rc4DecryptByte(fState, &fx, &fy, test2[j]);
|
||
|
}
|
||
|
+#endif
|
||
|
}
|
||
|
}
|
||
|
userPassword2 = new GooString((char *)test2, 32);
|
||
|
@@ -232,11 +324,15 @@ GBool Decrypt::makeFileKey2(int encVersi
|
||
|
GBool encryptMetadata) {
|
||
|
Guchar *buf;
|
||
|
Guchar test[32];
|
||
|
- Guchar fState[256];
|
||
|
Guchar tmpKey[16];
|
||
|
- Guchar fx, fy;
|
||
|
int len, i, j;
|
||
|
- GBool ok;
|
||
|
+ GBool ok = gTrue;
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ PK11Context *rc4Context;
|
||
|
+#else
|
||
|
+ Guchar fState[256];
|
||
|
+ Guchar fx, fy;
|
||
|
+#endif
|
||
|
|
||
|
// generate file key
|
||
|
buf = (Guchar *)gmalloc(72 + fileID->getLength());
|
||
|
@@ -273,28 +369,52 @@ GBool Decrypt::makeFileKey2(int encVersi
|
||
|
|
||
|
// test user password
|
||
|
if (encRevision == 2) {
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ rc4Context = rc4InitContext(fileKey, keyLength);
|
||
|
+ if (rc4Context) {
|
||
|
+ for (i = 0; i < 32; ++i)
|
||
|
+ test[i] = rc4DecryptByte(rc4Context, userKey->getChar(i));
|
||
|
+ PK11_DestroyContext(rc4Context, PR_TRUE);
|
||
|
+ } else {
|
||
|
+ ok = gFalse;
|
||
|
+ }
|
||
|
+#else
|
||
|
rc4InitKey(fileKey, keyLength, fState);
|
||
|
fx = fy = 0;
|
||
|
for (i = 0; i < 32; ++i) {
|
||
|
test[i] = rc4DecryptByte(fState, &fx, &fy, userKey->getChar(i));
|
||
|
}
|
||
|
- ok = memcmp(test, passwordPad, 32) == 0;
|
||
|
+#endif
|
||
|
+ if (ok)
|
||
|
+ ok = memcmp(test, passwordPad, 32) == 0;
|
||
|
} else if (encRevision == 3) {
|
||
|
memcpy(test, userKey->getCString(), 32);
|
||
|
for (i = 19; i >= 0; --i) {
|
||
|
for (j = 0; j < keyLength; ++j) {
|
||
|
tmpKey[j] = fileKey[j] ^ i;
|
||
|
}
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ rc4Context = rc4InitContext(tmpKey, keyLength);
|
||
|
+ if (rc4Context) {
|
||
|
+ for (j = 0; j < 32; ++j)
|
||
|
+ test[j] = rc4DecryptByte(rc4Context, test[j]);
|
||
|
+ PK11_DestroyContext(rc4Context, PR_TRUE);
|
||
|
+ } else {
|
||
|
+ ok = gFalse;
|
||
|
+ }
|
||
|
+#else
|
||
|
rc4InitKey(tmpKey, keyLength, fState);
|
||
|
fx = fy = 0;
|
||
|
for (j = 0; j < 32; ++j) {
|
||
|
test[j] = rc4DecryptByte(fState, &fx, &fy, test[j]);
|
||
|
}
|
||
|
+#endif
|
||
|
}
|
||
|
memcpy(buf, passwordPad, 32);
|
||
|
memcpy(buf + 32, fileID->getCString(), fileID->getLength());
|
||
|
md5(buf, 32 + fileID->getLength(), buf);
|
||
|
- ok = memcmp(test, buf, 16) == 0;
|
||
|
+ if (ok)
|
||
|
+ ok = memcmp(test, buf, 16) == 0;
|
||
|
} else {
|
||
|
ok = gFalse;
|
||
|
}
|
||
|
@@ -334,6 +454,9 @@ BaseCryptStream::BaseCryptStream(Stream
|
||
|
if ((objKeyLength = keyLength + 5) > 16) {
|
||
|
objKeyLength = 16;
|
||
|
}
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ state.rc4.context = nullptr;
|
||
|
+#endif
|
||
|
break;
|
||
|
case cryptAES:
|
||
|
objKey[keyLength] = objNum & 0xff;
|
||
|
@@ -349,9 +472,15 @@ BaseCryptStream::BaseCryptStream(Stream
|
||
|
if ((objKeyLength = keyLength + 5) > 16) {
|
||
|
objKeyLength = 16;
|
||
|
}
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ state.aes.context = nullptr;
|
||
|
+#endif
|
||
|
break;
|
||
|
case cryptAES256:
|
||
|
objKeyLength = keyLength;
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ state.aes256.context = nullptr;
|
||
|
+#endif
|
||
|
break;
|
||
|
case cryptNone:
|
||
|
break;
|
||
|
@@ -359,9 +488,32 @@ BaseCryptStream::BaseCryptStream(Stream
|
||
|
|
||
|
charactersRead = 0;
|
||
|
autoDelete = gTrue;
|
||
|
+
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ initNSS();
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
BaseCryptStream::~BaseCryptStream() {
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ switch (algo) {
|
||
|
+ case cryptRC4:
|
||
|
+ if (state.rc4.context)
|
||
|
+ PK11_DestroyContext(state.rc4.context, PR_TRUE);
|
||
|
+ break;
|
||
|
+ case cryptAES:
|
||
|
+ if (state.aes.context)
|
||
|
+ PK11_DestroyContext(state.aes.context, PR_TRUE);
|
||
|
+ break;
|
||
|
+ case cryptAES256:
|
||
|
+ if (state.aes256.context)
|
||
|
+ PK11_DestroyContext(state.aes256.context, PR_TRUE);
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ break;
|
||
|
+ }
|
||
|
+#endif
|
||
|
+
|
||
|
if (autoDelete) {
|
||
|
delete str;
|
||
|
}
|
||
|
@@ -424,18 +576,40 @@ void EncryptStream::reset() {
|
||
|
|
||
|
switch (algo) {
|
||
|
case cryptRC4:
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ if (state.rc4.context)
|
||
|
+ PK11_DestroyContext(state.rc4.context, PR_TRUE);
|
||
|
+ state.rc4.context = rc4InitContext(objKey, objKeyLength);
|
||
|
+#else
|
||
|
state.rc4.x = state.rc4.y = 0;
|
||
|
rc4InitKey(objKey, objKeyLength, state.rc4.state);
|
||
|
+#endif
|
||
|
break;
|
||
|
case cryptAES:
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ memcpy(state.aes.buf, state.aes.cbc, 16); // Copy CBC IV to buf
|
||
|
+ if (state.aes.context)
|
||
|
+ PK11_DestroyContext(state.aes.context, PR_TRUE);
|
||
|
+ state.aes.context = aesInitContext(state.aes.cbc, objKey, objKeyLength,
|
||
|
+ gFalse);
|
||
|
+#else
|
||
|
aesKeyExpansion(&state.aes, objKey, objKeyLength, gFalse);
|
||
|
memcpy(state.aes.buf, state.aes.cbc, 16); // Copy CBC IV to buf
|
||
|
+#endif
|
||
|
state.aes.bufIdx = 0;
|
||
|
state.aes.paddingReached = gFalse;
|
||
|
break;
|
||
|
case cryptAES256:
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ memcpy(state.aes256.buf, state.aes256.cbc, 16); // Copy CBC IV to buf
|
||
|
+ if (state.aes256.context)
|
||
|
+ PK11_DestroyContext(state.aes256.context, PR_TRUE);
|
||
|
+ state.aes256.context = aesInitContext(state.aes256.cbc, objKey, objKeyLength,
|
||
|
+ gFalse);
|
||
|
+#else
|
||
|
aes256KeyExpansion(&state.aes256, objKey, objKeyLength, gFalse);
|
||
|
memcpy(state.aes256.buf, state.aes256.cbc, 16); // Copy CBC IV to buf
|
||
|
+#endif
|
||
|
state.aes256.bufIdx = 0;
|
||
|
state.aes256.paddingReached = gFalse;
|
||
|
break;
|
||
|
@@ -456,7 +630,11 @@ int EncryptStream::lookChar() {
|
||
|
case cryptRC4:
|
||
|
if ((c = str->getChar()) != EOF) {
|
||
|
// RC4 is XOR-based: the decryption algorithm works for encryption too
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ c = rc4DecryptByte(state.rc4.context, (Guchar)c);
|
||
|
+#else
|
||
|
c = rc4DecryptByte(state.rc4.state, &state.rc4.x, &state.rc4.y, (Guchar)c);
|
||
|
+#endif
|
||
|
}
|
||
|
break;
|
||
|
case cryptAES:
|
||
|
@@ -506,21 +684,47 @@ void DecryptStream::reset() {
|
||
|
|
||
|
switch (algo) {
|
||
|
case cryptRC4:
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ if (state.rc4.context)
|
||
|
+ PK11_DestroyContext(state.rc4.context, PR_TRUE);
|
||
|
+ state.rc4.context = rc4InitContext(objKey, objKeyLength);
|
||
|
+#else
|
||
|
state.rc4.x = state.rc4.y = 0;
|
||
|
rc4InitKey(objKey, objKeyLength, state.rc4.state);
|
||
|
+#endif
|
||
|
break;
|
||
|
case cryptAES:
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ if (state.aes.context)
|
||
|
+ PK11_DestroyContext(state.aes.context, PR_TRUE);
|
||
|
+ for (i = 0; i < 16; ++i) {
|
||
|
+ state.aes.cbc[i] = str->getChar();
|
||
|
+ }
|
||
|
+ state.aes.context = aesInitContext(state.aes.cbc, objKey, objKeyLength,
|
||
|
+ gTrue);
|
||
|
+#else
|
||
|
aesKeyExpansion(&state.aes, objKey, objKeyLength, gTrue);
|
||
|
for (i = 0; i < 16; ++i) {
|
||
|
state.aes.cbc[i] = str->getChar();
|
||
|
}
|
||
|
+#endif
|
||
|
state.aes.bufIdx = 16;
|
||
|
break;
|
||
|
case cryptAES256:
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ if (state.aes256.context)
|
||
|
+ PK11_DestroyContext(state.aes256.context, PR_TRUE);
|
||
|
+ for (i = 0; i < 16; ++i) {
|
||
|
+ state.aes256.cbc[i] = str->getChar();
|
||
|
+ }
|
||
|
+ state.aes256.context = aesInitContext(state.aes256.cbc, objKey, objKeyLength,
|
||
|
+ gTrue);
|
||
|
+#else
|
||
|
aes256KeyExpansion(&state.aes256, objKey, objKeyLength, gTrue);
|
||
|
for (i = 0; i < 16; ++i) {
|
||
|
state.aes256.cbc[i] = str->getChar();
|
||
|
}
|
||
|
+#endif
|
||
|
state.aes256.bufIdx = 16;
|
||
|
break;
|
||
|
case cryptNone:
|
||
|
@@ -539,10 +743,21 @@ int DecryptStream::lookChar() {
|
||
|
switch (algo) {
|
||
|
case cryptRC4:
|
||
|
if ((c = str->getChar()) != EOF) {
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ if (unlikely(state.rc4.context == nullptr))
|
||
|
+ c = EOF;
|
||
|
+ else
|
||
|
+ c = rc4DecryptByte(state.rc4.context, (Guchar)c);
|
||
|
+#else
|
||
|
c = rc4DecryptByte(state.rc4.state, &state.rc4.x, &state.rc4.y, (Guchar)c);
|
||
|
+#endif
|
||
|
}
|
||
|
break;
|
||
|
case cryptAES:
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ if (unlikely(state.aes.context == nullptr))
|
||
|
+ break;
|
||
|
+#endif
|
||
|
if (state.aes.bufIdx == 16) {
|
||
|
if (aesReadBlock(str, in, gFalse)) {
|
||
|
aesDecryptBlock(&state.aes, in, str->lookChar() == EOF);
|
||
|
@@ -555,6 +770,10 @@ int DecryptStream::lookChar() {
|
||
|
}
|
||
|
break;
|
||
|
case cryptAES256:
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ if (unlikely(state.aes256.context == nullptr))
|
||
|
+ break;
|
||
|
+#endif
|
||
|
if (state.aes256.bufIdx == 16) {
|
||
|
if (aesReadBlock(str, in, gFalse)) {
|
||
|
aes256DecryptBlock(&state.aes256, in, str->lookChar() == EOF);
|
||
|
@@ -576,6 +795,175 @@ int DecryptStream::lookChar() {
|
||
|
// RC4-compatible decryption
|
||
|
//------------------------------------------------------------------------
|
||
|
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+/*
|
||
|
+ * This function turns given key into token key (compared to a session key
|
||
|
+ * which is prohibited in FIPS mode).
|
||
|
+ */
|
||
|
+static PK11SymKey *tokenizeKey(const Guchar *key, int keyLen,
|
||
|
+ CK_ATTRIBUTE_TYPE operation) {
|
||
|
+ CK_MECHANISM_TYPE cipherMech = CKM_AES_CBC_PAD;
|
||
|
+ PK11SlotInfo *slot;
|
||
|
+ PK11SymKey *wrappingKey = nullptr;
|
||
|
+ PK11SymKey *symKey = nullptr;
|
||
|
+ PK11SymKey *token = nullptr;
|
||
|
+ SECStatus retval;
|
||
|
+ SECItem *secParam = nullptr;
|
||
|
+ SECItem ivItem, wrappedKey;
|
||
|
+ Guchar output[48]; // Buffer to hold 256 bit key + padding
|
||
|
+ Guchar iv[16]; // Initialization vector for AES
|
||
|
+ Guint outputLength;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ slot = PK11_GetBestSlot(CKM_AES_KEY_GEN, nullptr);
|
||
|
+ if (slot == nullptr) {
|
||
|
+ error(errInternal, -1, "Unable to find security device (err {0:d})",
|
||
|
+ PR_GetError());
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ // Generate random key for wrapping of given key by AES-256
|
||
|
+ wrappingKey = PK11_KeyGen(slot, CKM_AES_KEY_GEN, nullptr, 32, nullptr);
|
||
|
+ if (wrappingKey == nullptr) {
|
||
|
+ error(errInternal, -1, "Failed to generate wrapping key (err {0:d})",
|
||
|
+ PR_GetError());
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ for (i = 0; i < 16; i++)
|
||
|
+ iv[i] = i;
|
||
|
+
|
||
|
+ ivItem.type = siBuffer;
|
||
|
+ ivItem.data = iv;
|
||
|
+ ivItem.len = 16;
|
||
|
+
|
||
|
+ secParam = PK11_ParamFromIV(cipherMech, &ivItem);
|
||
|
+ if (secParam == nullptr) {
|
||
|
+ error(errInternal, -1, "Failed to set up PKCS11 param (err {0:d})",
|
||
|
+ PR_GetError());
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ // Encrypt given key
|
||
|
+ retval = PK11_Encrypt(wrappingKey,
|
||
|
+ cipherMech,
|
||
|
+ secParam,
|
||
|
+ output,
|
||
|
+ &outputLength,
|
||
|
+ sizeof(output),
|
||
|
+ key,
|
||
|
+ keyLen);
|
||
|
+ if (retval != SECSuccess) {
|
||
|
+ error(errInternal, -1, "Failed to encrypt key (err {0:d})",
|
||
|
+ PR_GetError());
|
||
|
+ }
|
||
|
+
|
||
|
+ wrappedKey.type = siBuffer;
|
||
|
+ wrappedKey.data = output;
|
||
|
+ wrappedKey.len = outputLength;
|
||
|
+
|
||
|
+ // Unwrap the wrapped key to token so it can be used in FIPS mode
|
||
|
+ token = PK11_UnwrapSymKey(wrappingKey,
|
||
|
+ cipherMech,
|
||
|
+ &ivItem,
|
||
|
+ &wrappedKey,
|
||
|
+ operation,
|
||
|
+ CKA_UNWRAP,
|
||
|
+ keyLen);
|
||
|
+
|
||
|
+ if (token == nullptr) {
|
||
|
+ error(errInternal, -1, "Failed to unwrap symmetric key (err {0:d})",
|
||
|
+ PR_GetError());
|
||
|
+ }
|
||
|
+
|
||
|
+err:
|
||
|
+ if (secParam != nullptr)
|
||
|
+ SECITEM_FreeItem(secParam, PR_TRUE);
|
||
|
+
|
||
|
+ if (wrappingKey != nullptr)
|
||
|
+ PK11_FreeSymKey(wrappingKey);
|
||
|
+
|
||
|
+ if (symKey != nullptr)
|
||
|
+ PK11_FreeSymKey(symKey);
|
||
|
+
|
||
|
+ if (slot != nullptr)
|
||
|
+ PK11_FreeSlot(slot);
|
||
|
+
|
||
|
+ return token;
|
||
|
+}
|
||
|
+
|
||
|
+static PK11Context *rc4InitContext(const Guchar *key, int keyLen) {
|
||
|
+ CK_MECHANISM_TYPE cipherMech = CKM_RC4;
|
||
|
+ PK11SlotInfo *slot = nullptr;
|
||
|
+ PK11SymKey *symKey = nullptr;
|
||
|
+ SECItem *secParam = nullptr;
|
||
|
+ PK11Context *context = nullptr;
|
||
|
+
|
||
|
+ slot = PK11_GetBestSlot(cipherMech, nullptr);
|
||
|
+ if (slot == nullptr) {
|
||
|
+ error(errInternal, -1, "Unable to find security device (err {0:d})",
|
||
|
+ PR_GetError());
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ symKey = tokenizeKey(key, keyLen, cipherMech);
|
||
|
+ if (symKey == nullptr) {
|
||
|
+ error(errInternal, -1, "Failed to create token from key (err {0:d})",
|
||
|
+ PR_GetError());
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ secParam = PK11_ParamFromIV(cipherMech, nullptr);
|
||
|
+ if (secParam == nullptr) {
|
||
|
+ error(errInternal, -1, "Failed to set up PKCS11 param (err {0:d})",
|
||
|
+ PR_GetError());
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ context = PK11_CreateContextBySymKey(cipherMech,
|
||
|
+ CKA_DECRYPT,
|
||
|
+ symKey,
|
||
|
+ secParam);
|
||
|
+ if (context == nullptr) {
|
||
|
+ error(errInternal, -1, "Failed to create context (err {0:d})",
|
||
|
+ PR_GetError());
|
||
|
+ }
|
||
|
+
|
||
|
+err:
|
||
|
+ if (secParam != nullptr)
|
||
|
+ SECITEM_FreeItem(secParam, PR_TRUE);
|
||
|
+
|
||
|
+ if (symKey != nullptr)
|
||
|
+ PK11_FreeSymKey(symKey);
|
||
|
+
|
||
|
+ if (slot != nullptr)
|
||
|
+ PK11_FreeSlot(slot);
|
||
|
+
|
||
|
+ return context;
|
||
|
+}
|
||
|
+
|
||
|
+static Guchar rc4DecryptByte(PK11Context *context, Guchar c) {
|
||
|
+ Guchar outputChar = 0;
|
||
|
+ SECStatus retval;
|
||
|
+ int outputLength;
|
||
|
+
|
||
|
+ retval = PK11_CipherOp(context,
|
||
|
+ &outputChar,
|
||
|
+ &outputLength,
|
||
|
+ 1,
|
||
|
+ &c,
|
||
|
+ 1);
|
||
|
+
|
||
|
+ if (retval != SECSuccess) {
|
||
|
+ error(errInternal, -1, "Failed to decrypt byte (err {0:d})",
|
||
|
+ PR_GetError());
|
||
|
+ }
|
||
|
+
|
||
|
+ return outputChar;
|
||
|
+}
|
||
|
+
|
||
|
+#else
|
||
|
+
|
||
|
static void rc4InitKey(Guchar *key, int keyLen, Guchar *state) {
|
||
|
Guchar index1, index2;
|
||
|
Guchar t;
|
||
|
@@ -609,6 +997,8 @@ static Guchar rc4DecryptByte(Guchar *sta
|
||
|
return c ^ state[(tx + ty) % 256];
|
||
|
}
|
||
|
|
||
|
+#endif
|
||
|
+
|
||
|
//------------------------------------------------------------------------
|
||
|
// AES decryption
|
||
|
//------------------------------------------------------------------------
|
||
|
@@ -639,6 +1029,178 @@ static GBool aesReadBlock(Stream *str, G
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+
|
||
|
+static PK11Context *aesInitContext(Guchar *in, Guchar *objKey,
|
||
|
+ int objKeyLength, GBool decrypt) {
|
||
|
+ CK_MECHANISM_TYPE cipherMech = CKM_AES_CBC;
|
||
|
+ CK_ATTRIBUTE_TYPE operationType = decrypt ? CKA_DECRYPT : CKA_ENCRYPT;
|
||
|
+ PK11SlotInfo *slot;
|
||
|
+ PK11SymKey *symKey = nullptr;
|
||
|
+ SECItem *secParam = nullptr;
|
||
|
+ PK11Context *context = nullptr;
|
||
|
+ SECItem ivItem;
|
||
|
+
|
||
|
+ slot = PK11_GetBestSlot(cipherMech, nullptr);
|
||
|
+ if (slot == nullptr) {
|
||
|
+ error(errInternal, -1, "Unable to find security device (err {0:d})",
|
||
|
+ PR_GetError());
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ symKey = tokenizeKey(objKey, objKeyLength, cipherMech);
|
||
|
+ if (symKey == nullptr) {
|
||
|
+ error(errInternal, -1, "Failed to create token from key (err {0:d})",
|
||
|
+ PR_GetError());
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ ivItem.type = siBuffer;
|
||
|
+ ivItem.data = in;
|
||
|
+ ivItem.len = 16;
|
||
|
+
|
||
|
+ secParam = PK11_ParamFromIV(cipherMech, &ivItem);
|
||
|
+ if (secParam == nullptr) {
|
||
|
+ error(errInternal, -1, "Failed to set up PKCS11 param (err {0:d})",
|
||
|
+ PR_GetError());
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ context = PK11_CreateContextBySymKey(cipherMech,
|
||
|
+ operationType,
|
||
|
+ symKey,
|
||
|
+ secParam);
|
||
|
+
|
||
|
+err:
|
||
|
+ if (secParam != nullptr)
|
||
|
+ SECITEM_FreeItem(secParam, PR_TRUE);
|
||
|
+
|
||
|
+ if (symKey != nullptr)
|
||
|
+ PK11_FreeSymKey(symKey);
|
||
|
+
|
||
|
+ if (slot != nullptr)
|
||
|
+ PK11_FreeSlot(slot);
|
||
|
+
|
||
|
+ return context;
|
||
|
+}
|
||
|
+
|
||
|
+static void aesEncryptBlock(DecryptAESState *s, Guchar *in) {
|
||
|
+ SECStatus rv;
|
||
|
+ int outputLength;
|
||
|
+
|
||
|
+ rv = PK11_CipherOp(s->context,
|
||
|
+ s->buf,
|
||
|
+ &outputLength,
|
||
|
+ 16,
|
||
|
+ in,
|
||
|
+ 16);
|
||
|
+
|
||
|
+ if (rv != SECSuccess) {
|
||
|
+ error(errInternal, -1, "Failed to encrypt input block (err {0:d})",
|
||
|
+ PR_GetError());
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ s->bufIdx = 0;
|
||
|
+
|
||
|
+err:
|
||
|
+ return;
|
||
|
+}
|
||
|
+
|
||
|
+static void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last) {
|
||
|
+ SECStatus rv1;
|
||
|
+ int outputLen;
|
||
|
+ int n, i;
|
||
|
+
|
||
|
+ rv1 = PK11_CipherOp(s->context,
|
||
|
+ s->buf,
|
||
|
+ &outputLen,
|
||
|
+ 16,
|
||
|
+ in,
|
||
|
+ 16);
|
||
|
+
|
||
|
+ if (rv1 != SECSuccess) {
|
||
|
+ error(errInternal, -1, "Failed to decrypt input block (err {0:d})",
|
||
|
+ PR_GetError());
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ s->bufIdx = 0;
|
||
|
+ if (last) {
|
||
|
+ n = s->buf[15];
|
||
|
+ if (n < 1 || n > 16) { // this should never happen
|
||
|
+ n = 16;
|
||
|
+ }
|
||
|
+ for (i = 15; i >= n; --i) {
|
||
|
+ s->buf[i] = s->buf[i-n];
|
||
|
+ }
|
||
|
+ s->bufIdx = n;
|
||
|
+ }
|
||
|
+
|
||
|
+err:
|
||
|
+ return;
|
||
|
+}
|
||
|
+
|
||
|
+static void aes256EncryptBlock(DecryptAES256State *s, Guchar *in) {
|
||
|
+ SECStatus rv;
|
||
|
+ int outputLength;
|
||
|
+
|
||
|
+ rv = PK11_CipherOp(s->context,
|
||
|
+ s->buf,
|
||
|
+ &outputLength,
|
||
|
+ 16,
|
||
|
+ in,
|
||
|
+ 16);
|
||
|
+
|
||
|
+ if (rv != SECSuccess) {
|
||
|
+ error(errInternal, -1, "Failed to encrypt input block (err {0:d})",
|
||
|
+ PR_GetError());
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ s->bufIdx = 0;
|
||
|
+
|
||
|
+err:
|
||
|
+ return;
|
||
|
+}
|
||
|
+
|
||
|
+static void aes256DecryptBlock(DecryptAES256State *s, Guchar *in,
|
||
|
+ GBool last) {
|
||
|
+ SECStatus rv1;
|
||
|
+ int outputLen;
|
||
|
+ int n, i;
|
||
|
+
|
||
|
+ rv1 = PK11_CipherOp(s->context,
|
||
|
+ s->buf,
|
||
|
+ &outputLen,
|
||
|
+ 16,
|
||
|
+ in,
|
||
|
+ 16);
|
||
|
+
|
||
|
+ if (rv1 != SECSuccess) {
|
||
|
+ error(errInternal, -1, "Failed to decrypt input block (err {0:d})",
|
||
|
+ PR_GetError());
|
||
|
+ goto err;
|
||
|
+ }
|
||
|
+
|
||
|
+ s->bufIdx = 0;
|
||
|
+ if (last) {
|
||
|
+ n = s->buf[15];
|
||
|
+ if (n < 1 || n > 16) { // this should never happen
|
||
|
+ n = 16;
|
||
|
+ }
|
||
|
+ for (i = 15; i >= n; --i) {
|
||
|
+ s->buf[i] = s->buf[i-n];
|
||
|
+ }
|
||
|
+ s->bufIdx = n;
|
||
|
+ }
|
||
|
+
|
||
|
+err:
|
||
|
+ return;
|
||
|
+}
|
||
|
+
|
||
|
+#else
|
||
|
+
|
||
|
static const Guchar sbox[256] = {
|
||
|
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||
|
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
|
||
|
@@ -1121,10 +1683,33 @@ static void aes256DecryptBlock(DecryptAE
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+#endif
|
||
|
+
|
||
|
//------------------------------------------------------------------------
|
||
|
// MD5 message digest
|
||
|
//------------------------------------------------------------------------
|
||
|
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+static void hashFunc(const Guchar *msg, int msgLen, Guchar *hash,
|
||
|
+ HASH_HashType type) {
|
||
|
+ HASHContext *context;
|
||
|
+ Guint hashLen = 0;
|
||
|
+
|
||
|
+ if (!initNSS())
|
||
|
+ return;
|
||
|
+
|
||
|
+ context = HASH_Create(type);
|
||
|
+ if (context == nullptr)
|
||
|
+ return;
|
||
|
+
|
||
|
+ HASH_Begin(context);
|
||
|
+ HASH_Update(context, msg, msgLen);
|
||
|
+ HASH_End(context, hash, &hashLen, HASH_ResultLen(type));
|
||
|
+ HASH_Destroy(context);
|
||
|
+}
|
||
|
+
|
||
|
+#else
|
||
|
+
|
||
|
// this works around a bug in older Sun compilers
|
||
|
static inline Gulong rotateLeft(Gulong x, int r) {
|
||
|
x &= 0xffffffff;
|
||
|
@@ -1151,7 +1736,12 @@ static inline Gulong md5Round4(Gulong a,
|
||
|
return b + rotateLeft((a + (c ^ (b | ~d)) + Xk + Ti), s);
|
||
|
}
|
||
|
|
||
|
+#endif
|
||
|
+
|
||
|
void md5(Guchar *msg, int msgLen, Guchar *digest) {
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ hashFunc(msg, msgLen, digest, HASH_AlgMD5);
|
||
|
+#else
|
||
|
Gulong x[16] = {};
|
||
|
Gulong a, b, c, d, aa, bb, cc, dd;
|
||
|
int n64;
|
||
|
@@ -1296,12 +1886,14 @@ void md5(Guchar *msg, int msgLen, Guchar
|
||
|
digest[13] = (Guchar)((d >>= 8) & 0xff);
|
||
|
digest[14] = (Guchar)((d >>= 8) & 0xff);
|
||
|
digest[15] = (Guchar)((d >>= 8) & 0xff);
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
//------------------------------------------------------------------------
|
||
|
// SHA-256 hash
|
||
|
//------------------------------------------------------------------------
|
||
|
|
||
|
+#ifndef ENABLE_NSS3
|
||
|
static Guint sha256K[64] = {
|
||
|
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||
|
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||
|
@@ -1400,8 +1992,12 @@ static void sha256HashBlock(Guchar *blk,
|
||
|
H[6] += g;
|
||
|
H[7] += h;
|
||
|
}
|
||
|
+#endif
|
||
|
|
||
|
static void sha256(Guchar *msg, int msgLen, Guchar *hash) {
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ hashFunc(msg, msgLen, hash, HASH_AlgSHA256);
|
||
|
+#else
|
||
|
Guchar blk[64];
|
||
|
Guint H[8];
|
||
|
int blkLen, i;
|
||
|
@@ -1453,7 +2049,10 @@ static void sha256(Guchar *msg, int msgL
|
||
|
hash[i*4 + 2] = (Guchar)(H[i] >> 8);
|
||
|
hash[i*4 + 3] = (Guchar)H[i];
|
||
|
}
|
||
|
+#endif
|
||
|
}
|
||
|
+
|
||
|
+#ifndef ENABLE_NSS3
|
||
|
//------------------------------------------------------------------------
|
||
|
// SHA-512 hash (see FIPS 180-4)
|
||
|
//------------------------------------------------------------------------
|
||
|
@@ -1557,8 +2156,12 @@ static void sha512HashBlock(Guchar *blk,
|
||
|
H[6] += g;
|
||
|
H[7] += h;
|
||
|
}
|
||
|
+#endif
|
||
|
|
||
|
static void sha512(Guchar *msg, int msgLen, Guchar *hash) {
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ hashFunc(msg, msgLen, hash, HASH_AlgSHA512);
|
||
|
+#else
|
||
|
Guchar blk[128];
|
||
|
uint64_t H[8];
|
||
|
int blkLen = 0, i;
|
||
|
@@ -1622,6 +2225,7 @@ static void sha512(Guchar *msg, int msgL
|
||
|
hash[i*8 + 6] = (Guchar)(H[i] >> 8);
|
||
|
hash[i*8 + 7] = (Guchar)H[i];
|
||
|
}
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
//------------------------------------------------------------------------
|
||
|
@@ -1631,6 +2235,9 @@ static void sha512(Guchar *msg, int msgL
|
||
|
//1.Initial hash value is different.
|
||
|
//2.A 384 bit message digest is obtained by truncating the final hash value.
|
||
|
static void sha384(Guchar *msg, int msgLen, Guchar *hash) {
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ hashFunc(msg, msgLen, hash, HASH_AlgSHA384);
|
||
|
+#else
|
||
|
Guchar blk[128];
|
||
|
uint64_t H[8];
|
||
|
int blkLen, i;
|
||
|
@@ -1696,6 +2303,7 @@ static void sha384(Guchar *msg, int msgL
|
||
|
hash[i*8 + 6] = (Guchar)(H[i] >> 8);
|
||
|
hash[i*8 + 7] = (Guchar)H[i];
|
||
|
}
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
//------------------------------------------------------------------------
|
||
|
@@ -1725,7 +2333,8 @@ static void revision6Hash(GooString *inp
|
||
|
//a.make the string K1
|
||
|
memcpy(K1, inputPassword, inputPasswordLength);
|
||
|
memcpy(K1 + inputPasswordLength, K , KLength);
|
||
|
- memcpy(K1 + inputPasswordLength + KLength, userKey, userKeyLength);
|
||
|
+ if (userKey)
|
||
|
+ memcpy(K1 + inputPasswordLength + KLength, userKey, userKeyLength);
|
||
|
for(int i = 1; i < 64 ; ++i) {
|
||
|
memcpy(K1 + (i * sequenceLength),K1,sequenceLength);
|
||
|
}
|
||
|
@@ -1735,7 +2344,11 @@ static void revision6Hash(GooString *inp
|
||
|
memcpy(state.buf, state.cbc, 16); // Copy CBC IV to buf
|
||
|
state.bufIdx = 0;
|
||
|
state.paddingReached = gFalse;
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ state.context = aesInitContext(state.cbc, aesKey, 16, gFalse);
|
||
|
+#else
|
||
|
aesKeyExpansion(&state,aesKey,16,gFalse);
|
||
|
+#endif
|
||
|
|
||
|
for(int i = 0; i < (4 * sequenceLength); i++) {
|
||
|
aesEncryptBlock(&state,K1 + (16 * i));
|
||
|
@@ -1776,6 +2389,9 @@ static void revision6Hash(GooString *inp
|
||
|
sha512(E, totalLength, K);
|
||
|
}
|
||
|
rounds++;
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ PK11_DestroyContext(state.context, PR_TRUE);
|
||
|
+#endif
|
||
|
}
|
||
|
// the first 32 bytes of the final K are the output of the function.
|
||
|
}
|
||
|
diff --git a/poppler/Decrypt.h b/poppler/Decrypt.h
|
||
|
index d4667c8c..16fa9830 100644
|
||
|
--- a/poppler/Decrypt.h
|
||
|
+++ b/poppler/Decrypt.h
|
||
|
@@ -31,6 +32,9 @@
|
||
|
#include "goo/GooString.h"
|
||
|
#include "Object.h"
|
||
|
#include "Stream.h"
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+#include <pk11pub.h>
|
||
|
+#endif
|
||
|
|
||
|
//------------------------------------------------------------------------
|
||
|
// Decrypt
|
||
|
@@ -73,13 +77,21 @@ private:
|
||
|
* previous output is kept in buf. The paddingReached field is only used in
|
||
|
* case of encryption. */
|
||
|
struct DecryptRC4State {
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ PK11Context *context;
|
||
|
+#else
|
||
|
Guchar state[256];
|
||
|
Guchar x, y;
|
||
|
+#endif
|
||
|
};
|
||
|
|
||
|
struct DecryptAESState {
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ PK11Context *context;
|
||
|
+#else
|
||
|
Guint w[44];
|
||
|
Guchar state[16];
|
||
|
+#endif
|
||
|
Guchar cbc[16];
|
||
|
Guchar buf[16];
|
||
|
GBool paddingReached; // encryption only
|
||
|
@@ -87,8 +99,12 @@ struct DecryptAESState {
|
||
|
};
|
||
|
|
||
|
struct DecryptAES256State {
|
||
|
+#ifdef ENABLE_NSS3
|
||
|
+ PK11Context *context;
|
||
|
+#else
|
||
|
Guint w[60];
|
||
|
Guchar state[16];
|
||
|
+#endif
|
||
|
Guchar cbc[16];
|
||
|
Guchar buf[16];
|
||
|
GBool paddingReached; // encryption only
|
||
|
diff --git a/poppler/poppler-config.h.cmake b/poppler/poppler-config.h.cmake
|
||
|
index f0a5a1a0..dcaade6f 100644
|
||
|
--- a/poppler/poppler-config.h.cmake
|
||
|
+++ b/poppler/poppler-config.h.cmake
|
||
|
@@ -115,6 +115,12 @@
|
||
|
#cmakedefine USE_CMS 1
|
||
|
#endif
|
||
|
|
||
|
+/* Build against libnss3 for digital signature validation and
|
||
|
+ implementation of encryption/decryption. */
|
||
|
+#ifndef ENABLE_NSS3
|
||
|
+#cmakedefine ENABLE_NSS3 1
|
||
|
+#endif
|
||
|
+
|
||
|
// Also, there are preprocessor symbols in the header files
|
||
|
// that are used but never defined when building poppler using configure
|
||
|
// or cmake: DISABLE_OUTLINE, DEBUG_MEM,
|
||
|
--- poppler-0.66.0/CMakeLists.txt
|
||
|
+++ poppler-0.66.0/CMakeLists.txt
|
||
|
@@ -490,7 +490,7 @@ add_library(poppler STATIC ${poppler_SRC
|
||
|
else()
|
||
|
add_library(poppler ${poppler_SRCS})
|
||
|
endif()
|
||
|
-set_target_properties(poppler PROPERTIES VERSION 77.0.0 SOVERSION 77)
|
||
|
+set_target_properties(poppler PROPERTIES VERSION 78.0.0 SOVERSION 78)
|
||
|
if(MINGW)
|
||
|
get_target_property(POPPLER_SOVERSION poppler SOVERSION)
|
||
|
set_target_properties(poppler PROPERTIES SUFFIX "-${POPPLER_SOVERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}")
|