You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by bl...@apache.org on 2006/03/01 10:30:58 UTC
svn commit: r381962 - /xml/security/trunk/c/src/enc/XSECCryptoUtils.cpp
Author: blautenb
Date: Wed Mar 1 01:30:56 2006
New Revision: 381962
URL: http://svn.apache.org/viewcvs?rev=381962&view=rev
Log:
Partially implement SASLstringPrep for pass phrases as required for newer versions of XKMS spec
Modified:
xml/security/trunk/c/src/enc/XSECCryptoUtils.cpp
Modified: xml/security/trunk/c/src/enc/XSECCryptoUtils.cpp
URL: http://svn.apache.org/viewcvs/xml/security/trunk/c/src/enc/XSECCryptoUtils.cpp?rev=381962&r1=381961&r2=381962&view=diff
==============================================================================
--- xml/security/trunk/c/src/enc/XSECCryptoUtils.cpp (original)
+++ xml/security/trunk/c/src/enc/XSECCryptoUtils.cpp Wed Mar 1 01:30:56 2006
@@ -30,9 +30,11 @@
#include <xsec/enc/XSECCryptoUtils.hpp>
#include <xsec/enc/XSECCryptoKeyHMAC.hpp>
#include <xsec/utils/XSECPlatformUtils.hpp>
+#include <xsec/utils/XSECDOMUtils.hpp>
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/XMLString.hpp>
+#include <xercesc/util/XMLUniDefs.hpp>
XERCES_CPP_NAMESPACE_USE
@@ -42,6 +44,7 @@
int CleanXKMSPassPhrase(unsigned char * input, int inputLen, safeBuffer &output) {
+ // Now obsolete - use SASLCleanXKMSPassPhrase instead
int j = 0;
unsigned char c;
for (int i = 0; i < inputLen; ++i) {
@@ -61,6 +64,185 @@
}
+int SASLCleanXKMSPassPhrase(unsigned char * input, int inputLen, safeBuffer &output) {
+
+ // For now - this does *not* implement the full SASLPrep algorithm.
+ // THe NFKC form is not trivial to implement - so this is kept very simple.
+ // TODO - Fix this - it can be an interoperability issue as pass phrases from
+ // different implementations could be treated differently.
+ // Currently we only check for prohibited unput for chars < 0xFFFF and drop any
+ // chars over 0xFFFF
+
+ XMLCh * uinput, *uoutput;
+ unsigned char * inp = new unsigned char[inputLen + 1];
+ ArrayJanitor<unsigned char> j_inp(inp);
+ memcpy(inp, input, inputLen);
+ inp[inputLen] = '\0';
+
+ uinput = XMLString::transcode((char *) inp);
+ unsigned int l = XMLString::stringLen(uinput);
+ uoutput = new XMLCh[l + 1];
+ ArrayJanitor<XMLCh> j_uinput(uinput);
+ ArrayJanitor<XMLCh> j_uoutput(uoutput);
+
+ unsigned int i, j;
+ j = 0;
+
+ XMLCh ch1;
+
+ for (i = 0; i < l; ++i) {
+
+ ch1 = uinput[i];
+ // Case one - char is < 0x10000
+ if (ch1 < 0xD800 || ch1 > 0xDFFF) {
+
+ // OK - ch1 is "real" value - let's see if it is legal
+ // The following switch tables are derived from
+ // RFC 3454 - see http://www.ietf.org/rfc/rfc3454.txt
+
+ // Non-ASCII Spaces - C.1.2
+ switch (ch1) {
+
+ case 0x00A0: // NO-BREAK SPACE
+ case 0x1680: // OGHAM SPACE MARK
+ case 0x2000: // EN QUAD
+ case 0x2001: // EM QUAD
+ case 0x2002: // EN SPACE
+ case 0x2003: // EM SPACE
+ case 0x2004: // THREE-PER-EM SPACE
+ case 0x2005: // FOUR-PER-EM SPACE
+ case 0x2006: // SIX-PER-EM SPACE
+ case 0x2007: // FIGURE SPACE
+ case 0x2008: // PUNCTUATION SPACE
+ case 0x2009: // THIN SPACE
+ case 0x200A: // HAIR SPACE
+ case 0x200B: // ZERO WIDTH SPACE
+ case 0x202F: // NARROW NO-BREAK SPACE
+ case 0x205F: // MEDIUM MATHEMATICAL SPACE
+ case 0x3000: // IDEOGRAPHIC SPACE
+
+ throw XSECException(XSECException::XKMSError,
+ "SASLCleanXKMSPassPhrase - Non ASCII space character in XKMS pass phrase");
+ default:
+
+ break;
+
+ }
+
+ // ASCII Control characters
+ if ((ch1 >=0 && ch1 <= 0x1F) || ch1 == 0x7F) {
+ throw XSECException(XSECException::XKMSError,
+ "SASLCleanXKMSPassPhrase - ASCII control character in XKMS pass phrase");
+ }
+
+ // Non-ASCII Control Characters
+ if ((ch1 >= 0x80 && ch1 <= 0x9F) ||
+ (ch1 >= 0x206A && ch1 <= 0x206F) ||
+ (ch1 >= 0xFFF9 && ch1 <= 0xFFFC)) {
+
+ throw XSECException(XSECException::XKMSError,
+ "SASLCleanXKMSPassPhrase - NON ASCII control character in XKMS pass phrase");
+ }
+
+ switch (ch1) {
+
+
+ case 0x06DD: // ARABIC END OF AYAH
+ case 0x070F: // SYRIAC ABBREVIATION MARK
+ case 0x180E: // MONGOLIAN VOWEL SEPARATOR
+ case 0x200C: // ZERO WIDTH NON-JOINER
+ case 0x200D: // ZERO WIDTH JOINER
+ case 0x2028: // LINE SEPARATOR
+ case 0x2029: // PARAGRAPH SEPARATOR
+ case 0x2060: // WORD JOINER
+ case 0x2061: // FUNCTION APPLICATION
+ case 0x2062: // INVISIBLE TIMES
+ case 0x2063: // INVISIBLE SEPARATOR
+ case 0xFEFF: // ZERO WIDTH NO-BREAK SPACE
+ throw XSECException(XSECException::XKMSError,
+ "SASLCleanXKMSPassPhrase - NON ASCII control character in XKMS pass phrase");
+ default:
+ break; }
+ // 1D173-1D17A; [MUSICAL CONTROL CHARACTERS] is not relevant as we are looking at
+ // ch1 at the moment
+
+ // Private Use characters
+ if ((ch1 >= 0xE000 && ch1 <= 0xF8FF)) {
+
+ throw XSECException(XSECException::XKMSError,
+ "SASLCleanXKMSPassPhrase - Private Use character in XKMS pass phrase");
+ }
+
+ // Non-character code points
+ if ((ch1 >= 0xFDD0 && ch1 <= 0xFDEF) ||
+ (ch1 >= 0xFFFE && ch1 <= 0xFFFF)) {
+
+ throw XSECException(XSECException::XKMSError,
+ "SASLCleanXKMSPassPhrase - Non-character code points in XKMS pass phrase");
+ }
+
+ // Inappropriate for plain text characters
+
+ switch (ch1) {
+ case 0xFFF9: // INTERLINEAR ANNOTATION ANCHOR
+ case 0xFFFA: // INTERLINEAR ANNOTATION SEPARATOR
+ case 0xFFFB: // INTERLINEAR ANNOTATION TERMINATOR
+ case 0xFFFC: // OBJECT REPLACEMENT CHARACTER
+ case 0xFFFD: // REPLACEMENT CHARACTER
+ throw XSECException(XSECException::XKMSError,
+ "SASLCleanXKMSPassPhrase - Innappropriate for plain text chararcters in XKMS pass phrase");
+ default:
+ break;
+ }
+
+ // Inappripriate for canonical representation characters
+ if (ch1 >= 0x2FF0 && ch1 <= 0x2FFB) {
+ throw XSECException(XSECException::XKMSError,
+ "SASLCleanXKMSPassPhrase - Innappropriate for canonicalisation chararcters in XKMS pass phrase");
+ }
+
+ // Change display properties or are deprecated
+ switch (ch1) {
+ case 0x0340: // COMBINING GRAVE TONE MARK
+ case 0x0341: // COMBINING ACUTE TONE MARK
+ case 0x200E: // LEFT-TO-RIGHT MARK
+ case 0x200F: // RIGHT-TO-LEFT MARK
+ case 0x202A: // LEFT-TO-RIGHT EMBEDDING
+ case 0x202B: // RIGHT-TO-LEFT EMBEDDING
+ case 0x202C: // POP DIRECTIONAL FORMATTING
+ case 0x202D: // LEFT-TO-RIGHT OVERRIDE
+ case 0x202E: // RIGHT-TO-LEFT OVERRIDE
+ case 0x206A: // INHIBIT SYMMETRIC SWAPPING
+ case 0x206B: // ACTIVATE SYMMETRIC SWAPPING
+ case 0x206C: // INHIBIT ARABIC FORM SHAPING
+ case 0x206D: // ACTIVATE ARABIC FORM SHAPING
+ case 0x206E: // NATIONAL DIGIT SHAPES
+ case 0x206F: // NOMINAL DIGIT SHAPES
+ throw XSECException(XSECException::XKMSError,
+ "SASLCleanXKMSPassPhrase - change display or deprecated chararcters in XKMS pass phrase");
+ default:
+ break;
+ }
+
+ // We got this far = just run with it for now
+ uoutput[j++] = ch1;
+ }
+ else {
+ throw XSECException(XSECException::XKMSError,
+ "SASLCleanXKMSPassPhrase - don't support XKMS pass phrase chars > 0xFFFF");
+ }
+ } /* for */
+ uoutput[j++] = chNull;
+
+ // Now transcode
+ char * utf8output= transcodeToUTF8(uoutput);
+ ArrayJanitor<char> j_utf8output(utf8output);
+ output.sbStrcpyIn(utf8output);
+
+ return strlen(utf8output);
+
+}
+
int DSIG_EXPORT CalculateXKMSAuthenticationKey(unsigned char * input, int inputLen, unsigned char * output, int maxOutputLen) {
unsigned char keyVal[] = {XKMSAuthenticationValue};
@@ -135,21 +317,45 @@
int DSIG_EXPORT CalculateXKMSKEK(unsigned char * input, int inputLen, unsigned char * output, int maxOutputLen) {
unsigned char keyVal[] = {XKMSKeyEncryption};
-
- XSECCryptoKeyHMAC * k = XSECPlatformUtils::g_cryptoProvider->keyHMAC();
- k->setKey(keyVal, 1);
-
- XSECCryptoHash *h = XSECPlatformUtils::g_cryptoProvider->hashHMACSHA1();
- Janitor<XSECCryptoHash> j_h(h);
-
- h->setKey(k);
+ unsigned char shaOutput[22]; // SHA1 has 20 bytes of output
// Clean the input
safeBuffer sb;
- int l = CleanXKMSPassPhrase(input, inputLen, sb);
+ int l = SASLCleanXKMSPassPhrase(input, inputLen, sb);
- h->hash((unsigned char *) sb.rawBuffer(), l);
- return h->finish(output, maxOutputLen);
+ // Need to iterate through until we have enough data
+ int bytesDone = 0, bytesToDo;;
+ shaOutput[0] = keyVal[0];
+ int keyLen = 1;
+ while (bytesDone < maxOutputLen) {
+ XSECCryptoKeyHMAC * k = XSECPlatformUtils::g_cryptoProvider->keyHMAC();
+ k->setKey(shaOutput, keyLen);
+
+ XSECCryptoHash *h = XSECPlatformUtils::g_cryptoProvider->hashHMACSHA1();
+ Janitor<XSECCryptoHash> j_h(h);
+
+ h->setKey(k);
+ delete(k);
+
+ // Now hash next round of data
+ h->hash((unsigned char *) sb.rawBuffer(), l);
+ keyLen = h->finish(shaOutput, 22);
+
+ // Copy into the output buffer
+ bytesToDo = maxOutputLen - bytesDone;
+ bytesToDo = bytesToDo > 20 ? 20 : bytesToDo;
+ memcpy(&output[bytesDone], shaOutput, bytesToDo);
+ bytesDone += bytesToDo;
+
+ // Set up for next key
+ shaOutput[0] ^= keyVal[0];
+ keyLen = 20;
+
+ j_h.release();
+ delete h;
+ }
+
+ return bytesDone;
}