static int rsaGenerateKey( CONTEXT_INFO *contextInfoPtr, const int keySizeBits ) { CRYPT_PKCINFO_RSA rsaKeyInfo; PERSONALITY_INFO *personalityInfoPtr; int keyHandle, status; assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) ); REQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \ keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) ); /* Find a free personality slot to store the key */ status = findFreePersonality( &keyHandle ); if( cryptStatusError( status ) ) return( status ); personalityInfoPtr = &personalityInfo[ keyHandle ]; /* Since the hardware doesn't provide native keygen capabilities we generate the key components using the helper function in hardware.c */ status = generatePKCcomponents( contextInfoPtr, &rsaKeyInfo, keySizeBits ); if( cryptStatusError( status ) ) { deletePersonality( keyHandle ); return( status ); } rsaKeyToInternal( personalityInfoPtr->keyInfo.pkcKeyInfo, &rsaKeyInfo ); zeroise( &rsaKeyInfo, sizeof( CRYPT_PKCINFO_RSA ) ); return( completeInitKeyRSA( contextInfoPtr, personalityInfoPtr, keyHandle ) ); }
static int generateKeyComponents( CONTEXT_INFO *staticContextInfo, PKC_INFO *contextData, const CAPABILITY_INFO *capabilityInfoPtr, const int keySizeBits ) { int status; assert( isWritePtr( staticContextInfo, sizeof( CONTEXT_INFO ) ) ); assert( isWritePtr( contextData, sizeof( PKC_INFO ) ) ); assert( isReadPtr( capabilityInfoPtr, sizeof( CAPABILITY_INFO ) ) ); REQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \ keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) ); /* Initialise a static context to generate the key into */ status = staticInitContext( staticContextInfo, CONTEXT_PKC, capabilityInfoPtr, contextData, sizeof( PKC_INFO ), NULL ); if( cryptStatusError( status ) ) return( status ); /* Generate a key into the static context */ status = capabilityInfoPtr->generateKeyFunction( staticContextInfo, keySizeBits ); if( cryptStatusError( status ) ) { staticDestroyContext( staticContextInfo ); return( status ); } return( CRYPT_OK ); }
static int aesGenerateKey( CONTEXT_INFO *contextInfoPtr, const int keySizeBits ) { PERSONALITY_INFO *personalityInfoPtr; const int keyLength = bitsToBytes( keySizeBits ); int keyHandle, status; assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) ); REQUIRES( keySizeBits >= bytesToBits( MIN_KEYSIZE ) && \ keySizeBits <= bytesToBits( CRYPT_MAX_KEYSIZE ) ); /* Find a free personality slot to store the key */ status = findFreePersonality( &keyHandle ); if( cryptStatusError( status ) ) return( status ); personalityInfoPtr = &personalityInfo[ keyHandle ]; /* Use the hardware RNG to generate the encryption key */ status = hwGetRandom( personalityInfoPtr->keyInfo.convKeyInfo, keyLength ); if( cryptStatusError( status ) ) { deletePersonality( keyHandle ); return( status ); } return( completeInitKeyAES( contextInfoPtr, personalityInfoPtr, keyHandle, keyLength ) ); }
void LteLicenseToolDialog::onOkClicked() { QTextStream ts(&log); //import decoded license QByteArray bytes; QFile file("./decoded_license.lic"); if(!file.open(QIODevice::ReadOnly)) { ts << tr("%1: %2:%3: Fail to open file: %4").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")).arg(__FILE__).arg(__LINE__).arg(file.fileName()); ts << "\n"; return; } bytes = file.readAll(); file.close(); hostName = hostNameEdit->text().trimmed(); hardwareName = hardwareNameEdit->text().trimmed(); bool ok; validPeriod = validPeriodEdit->text().trimmed().toUInt(&ok); if(hostName.isEmpty() || hardwareName.isEmpty() || !ok) { ts << tr("%1: %2:%3: Host name, Hardware name and Valid period must not be empty!").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")).arg(__FILE__).arg(__LINE__); ts << "\n"; return; } QDateTime dt = QDateTime::currentDateTimeUtc(); dt = dt.addDays(validPeriod); QString validTime = dt.toString("yyyyMMddHHmmss"); QString magicNumber = "7F51"; QString key1 = hardwareName + ";;" + hostName + ";;" + validTime; key1 = magicNumber + key1; QString key2 = "61431749"; QBitArray bits = bytesToBits(bytes); QBitArray bitsKey1 = bytesToBits(QByteArray::fromStdString(key1.toStdString())); QBitArray bitsKey2 = bytesToBits(QByteArray::fromStdString(key2.toStdString())); bits ^= bitsKey1; bits ^= bitsKey2; QByteArray bytes2 = bitsToBytes(bits); //export license file.setFileName("./license.lic"); if(!file.open(QIODevice::WriteOnly)) { ts << tr("%1: %2:%3: Fail to open file: %4").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")).arg(__FILE__).arg(__LINE__).arg(file.fileName()); ts << "\n"; return; } file.write(bytes2); file.close(); }
static int readPgpRsaPrivateKey( INOUT STREAM *stream, INOUT CONTEXT_INFO *contextInfoPtr ) { PKC_INFO *rsaKey = contextInfoPtr->ctxPKC; int status; assert( isWritePtr( stream, sizeof( STREAM ) ) ); assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) ); REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \ contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA ); /* Read the PGP private key information. Note that we have to read the d value here because we need it to calculate e1 and e2 */ status = readBignumInteger16Ubits( stream, &rsaKey->rsaParam_d, bytesToBits( RSAPARAM_MIN_D ), bytesToBits( RSAPARAM_MAX_D ), &rsaKey->rsaParam_n ); if( cryptStatusOK( status ) ) status = readBignumInteger16Ubits( stream, &rsaKey->rsaParam_p, bytesToBits( RSAPARAM_MIN_P ), bytesToBits( RSAPARAM_MAX_P ), &rsaKey->rsaParam_n ); if( cryptStatusOK( status ) ) status = readBignumInteger16Ubits( stream, &rsaKey->rsaParam_q, bytesToBits( RSAPARAM_MIN_Q ), bytesToBits( RSAPARAM_MAX_Q ), &rsaKey->rsaParam_n ); if( cryptStatusOK( status ) ) status = readBignumInteger16Ubits( stream, &rsaKey->rsaParam_u, bytesToBits( RSAPARAM_MIN_U ), bytesToBits( RSAPARAM_MAX_U ), &rsaKey->rsaParam_n ); return( status ); }
static int rsaGenerateComponents( CRYPT_PKCINFO_RSA *rsaKeyInfo, const int keySizeBits ) { CONTEXT_INFO staticContextInfo; PKC_INFO contextData, *pkcInfo = &contextData; int length, status; assert( isWritePtr( rsaKeyInfo, sizeof( CRYPT_PKCINFO_RSA ) ) ); REQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \ keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) ); /* Clear return value */ cryptInitComponents( rsaKeyInfo, FALSE ); /* Generate the key components */ status = generateKeyComponents( &staticContextInfo, &contextData, getRSACapability(), keySizeBits ); if( cryptStatusError( status ) ) return( status ); /* Extract the newly-generated key components for the caller to use */ rsaKeyInfo->nLen = BN_num_bits( &pkcInfo->rsaParam_n ); length = BN_bn2bin( &pkcInfo->rsaParam_n, rsaKeyInfo->n ); ENSURES( length == bitsToBytes( rsaKeyInfo->nLen ) ); rsaKeyInfo->eLen = BN_num_bits( &pkcInfo->rsaParam_e ); length = BN_bn2bin( &pkcInfo->rsaParam_e, rsaKeyInfo->e ); ENSURES( length == bitsToBytes( rsaKeyInfo->eLen ) ); rsaKeyInfo->pLen = BN_num_bits( &pkcInfo->rsaParam_p ); length = BN_bn2bin( &pkcInfo->rsaParam_p, rsaKeyInfo->p ); ENSURES( length == bitsToBytes( rsaKeyInfo->pLen ) ); rsaKeyInfo->qLen = BN_num_bits( &pkcInfo->rsaParam_q ); length = BN_bn2bin( &pkcInfo->rsaParam_q, rsaKeyInfo->q ); ENSURES( length == bitsToBytes( rsaKeyInfo->qLen ) ); rsaKeyInfo->e1Len = BN_num_bits( &pkcInfo->rsaParam_exponent1 ); length = BN_bn2bin( &pkcInfo->rsaParam_exponent1, rsaKeyInfo->e1 ); ENSURES( length == bitsToBytes( rsaKeyInfo->e1Len ) ); rsaKeyInfo->e2Len = BN_num_bits( &pkcInfo->rsaParam_exponent2 ); length = BN_bn2bin( &pkcInfo->rsaParam_exponent2, rsaKeyInfo->e2 ); ENSURES( length == bitsToBytes( rsaKeyInfo->e2Len ) ); rsaKeyInfo->uLen = BN_num_bits( &pkcInfo->rsaParam_u ); length = BN_bn2bin( &pkcInfo->rsaParam_u, rsaKeyInfo->u ); ENSURES( length == bitsToBytes( rsaKeyInfo->uLen ) ); staticDestroyContext( &staticContextInfo ); return( status ); }
static int readPgpDlpPrivateKey( INOUT STREAM *stream, INOUT CONTEXT_INFO *contextInfoPtr ) { PKC_INFO *dlpKey = contextInfoPtr->ctxPKC; assert( isWritePtr( stream, sizeof( STREAM ) ) ); assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) ); REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \ ( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DSA || \ contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_ELGAMAL ) ); /* Read the PGP private key information */ return( readBignumInteger16Ubits( stream, &dlpKey->dlpParam_x, bytesToBits( DLPPARAM_MIN_X ), bytesToBits( DLPPARAM_MAX_X ), &dlpKey->dlpParam_p ) ); }
int generatePKCcomponents( CONTEXT_INFO *contextInfoPtr, void *keyInfo, const int keySizeBits ) { const CRYPT_ALGO_TYPE cryptAlgo = \ contextInfoPtr->capabilityInfo->cryptAlgo; int status; assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) ); REQUIRES( keyInfo != NULL ); REQUIRES( cryptAlgo == CRYPT_ALGO_DH || \ cryptAlgo == CRYPT_ALGO_RSA || \ cryptAlgo == CRYPT_ALGO_DSA || \ cryptAlgo == CRYPT_ALGO_ELGAMAL ); REQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \ keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) ); switch( cryptAlgo ) { case CRYPT_ALGO_RSA: status = rsaGenerateComponents( keyInfo, keySizeBits ); break; #if defined( USE_DH ) || defined( USE_DSA ) || defined( USE_ELGAMAL ) case CRYPT_ALGO_DH: case CRYPT_ALGO_DSA: case CRYPT_ALGO_ELGAMAL: status = dlpGenerateComponents( keyInfo, keySizeBits, cryptAlgo ); break; #endif /* USE_DH || USE_DSA || USE_ELGAMAL */ default: return( CRYPT_ERROR_NOTAVAIL ); } if( cryptStatusError( status ) ) return( status ); /* Send the public-key data (needed for certificates and the like) to the context */ return( setPKCinfo( contextInfoPtr, cryptAlgo, keyInfo ) ); }
value is first truncated to its leftmost nlen bits if nlen is smaller than the hash value bit length before conversion to a bignum. Mathematically, this is equivalent to first converting the value to a bignum and then right-shifting it by hlen - nlen bits, where hlen is the hash length in bits (a more generic way to view the required conversion is 'while( BN_num_bits( hash ) > BN_num_bits( n ) { BN_rshift( hash, 1 ); }'). Finally, we reduce the value modulo n, which is a simple matter of a compare-and-subtract */ CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \ static int hashToBignum( INOUT BIGNUM *bignum, IN_BUFFER( hashLength ) const void *hash, IN_LENGTH_HASH const int hashLength, const BIGNUM *n ) { const int hLen = bytesToBits( hashLength ); const int nLen = BN_num_bits( n ); int bnStatus = BN_STATUS, status; assert( isWritePtr( bignum, sizeof( BIGNUM ) ) ); assert( isReadPtr( hash, hashLength ) ); assert( isReadPtr( n, sizeof( BIGNUM ) ) ); REQUIRES( sanityCheckBignum( bignum ) ); REQUIRES( hashLength >= 20 && hashLength <= CRYPT_MAX_HASHSIZE ); REQUIRES( nLen >= 20 && nLen <= bytesToBits( CRYPT_MAX_PKCSIZE_ECC ) ); /* Convert the hash value into a bignum. We have to be careful when we specify the bounds because, with increasingly smaller probabilities, the leading bytes of the hash value may be zero. The check used here gives one in 4 billion chance of a false
int main(int argc, char **argv) { QApplication app(argc, argv); //software license validation bool isValid = false; QString validTime; // QFile logFile("./output/decoded_str.lic"); // logFile.open(QIODevice::Append); QFile file("./config/license.lic"); if(!file.open(QIODevice::ReadOnly)) { //logFile.write("Fail to open license file"); return 1; } QByteArray bytes = file.readAll(); file.close(); file.setFileName("./config/decoded_license.lic"); if(!file.open(QIODevice::ReadOnly)) { //logFile.write("Fail to open decoded license file"); return 1; } QByteArray bytesDecoded = file.readAll(); file.close(); QString hostName = QHostInfo::localHostName(); QList<QNetworkInterface> ifList = QNetworkInterface::allInterfaces(); for(QList<QNetworkInterface>::iterator it = ifList.begin(); it != ifList.end(); ++it) { QString hardwareName = it->hardwareAddress().replace(':', '-'); QString magicNumber = "7F51"; QString key1 = hardwareName + ";;" + hostName + ";;"; key1 = magicNumber + key1; QString key2 = "61431749"; QBitArray bits = bytesToBits(bytes); QBitArray bitsDecoded = bytesToBits(bytesDecoded); QBitArray bitsKey1 = bytesToBits(QByteArray::fromStdString(key1.toStdString())); QBitArray bitsKey2 = bytesToBits(QByteArray::fromStdString(key2.toStdString())); bits ^= bitsDecoded; bits ^= bitsKey2; bits ^= bitsKey1; QByteArray bytes2 = bitsToBytes(bits); validTime = QString::fromStdString(bytes2.toStdString()).mid(key1.size(), QString("yyyymmddhhmmss").size()); //already UTC timezone if(validTime.isNull() || validTime.size() < QString("yyyymmddhhmmss").size()) { continue; } QDateTime dt = QDateTime::currentDateTimeUtc(); QString curTime = dt.toString("yyyyMMddHHmmss"); //1st check: time valid? bool timeValid = false; if(curTime < validTime) { timeValid = true; } //2nd check: license valid? bool licValid = true; for(int i = 0; i < bytes2.size(); ++i) { if(i >= key1.size() && i <= key1.size() + validTime.size() - 1) { continue; } else if(bytes2.at(i) != '\0') { licValid = false; break; } } if(timeValid && licValid) { isValid = true; // logFile.write("\n----------\n"); // logFile.write(key1.toStdString().c_str()); // logFile.write("\n"); // logFile.write(bytes2); // logFile.write("\n"); // logFile.write(validTime.toStdString().c_str()); // logFile.write("\n----------\n"); break; } } // logFile.close(); LteMainWindow mainWin(validTime); if(isValid) { mainWin.show(); } return app.exec(); }
void LteMainWindow::decodeLicense() { log->append(tr("localDomainName=%1, localHostName=%2").arg(QHostInfo::localDomainName()).arg(QHostInfo::localHostName())); QList<QNetworkInterface> ifList = QNetworkInterface::allInterfaces(); for(QList<QNetworkInterface>::iterator it = ifList.begin(); it != ifList.end(); ++it) { log->append(tr("name=%1, hardwareAddress=%2").arg(it->humanReadableName()).arg(it->hardwareAddress())); } QString magicNumber = "7F51"; QString hostName = "SC4GUIS2"; QString hardwareName = "00-50-56-AF-58-53"; QString validTime = "20160205180554"; QDateTime dt = QDateTime::fromString(validTime, "yyyyMMddHHmmss"); dt = dt.toUTC(); validTime = dt.toString("yyyyMMddHHmmss"); QString key1; //key1 = hardwareName.replace("-", ":") + ";;" + hostName + ";;" + validTime; //key1 = hostName + ";;" + hardwareName.replace("-", ":") + ";;" + validTime; key1 = hardwareName + ";;" + hostName + ";;" + validTime; //key1 = hostName + ";;" + hardwareName + ";;" + validTime; QString key2 = "61431749"; key1 = magicNumber + key1; QFile file("D:\\projects\\LteToolset2\\license.lic_28"); if(!file.open(QIODevice::ReadOnly)) { log->append(tr("Fail to open file: %1").arg(file.fileName())); } QByteArray bytes = file.readAll(); file.close(); log->append(tr("size of source text:%1, source text:%2").arg(bytes.count()).arg(QString::fromStdString(bytes.toStdString()))); QBitArray bits = bytesToBits(bytes); QBitArray bitsKey1 = bytesToBits(QByteArray::fromStdString(key1.toStdString())); QBitArray bitsKey2 = bytesToBits(QByteArray::fromStdString(key2.toStdString())); bits ^= bitsKey2; bits ^= bitsKey1; QByteArray bytes2 = bitsToBytes(bits); QString str3 = QString::fromStdString(bytes2.toStdString()); log->append(tr("size of bytes2: %1, decoded text:%2").arg(bytes2.count()).arg(str3)); file.setFileName("D:\\decoded_license.lic"); file.open(QIODevice::WriteOnly); file.write(bytes2); file.close(); hostName = "5CG4511M9Y"; hardwareName = "EC-B1-D7-9A-8F-28"; //hostName = "SC4GUIS2"; //hardwareName = "00-50-56-AF-58-53"; validTime = "20160105104900"; dt = QDateTime::fromString(validTime, "yyyyMMddHHmmss"); dt = dt.toUTC(); validTime = dt.toString("yyyyMMddHHmmss"); log->append(tr("valid time=%1").arg(validTime)); //key1 = hardwareName.replace("-", ":") + ";;" + hostName + ";;" + validTime; //key1 = hostName + ";;" + hardwareName.replace("-", ":") + ";;" + validTime; key1 = hardwareName + ";;" + hostName + ";;" + validTime; //key1 = hostName + ";;" + hardwareName + ";;" + validTime; key1 = magicNumber + key1; QBitArray bits2 = bytesToBits(bytes2); bitsKey1 = bytesToBits(QByteArray::fromStdString(key1.toStdString())); bitsKey2 = bytesToBits(QByteArray::fromStdString(key2.toStdString())); bits2 ^= bitsKey1; bits2 ^= bitsKey2; QByteArray bytes3 = bitsToBytes(bits2); log->append(tr("size of bytes3: %1").arg(bytes3.count())); file.setFileName("D:\\license.lic"); if(!file.open(QIODevice::WriteOnly)) { log->append(tr("Fail to open file: %1").arg(file.fileName())); } file.write(bytes3); file.close(); }
CHECK_RETVAL \ int loadDHcontext( IN_HANDLE const CRYPT_CONTEXT iDHContext, IN_LENGTH_SHORT_OPT const int requestedKeySize ) { MESSAGE_DATA msgData; const void *keyData; const int actualKeySize = \ ( requestedKeySize < 128 + 8 ) ? bitsToBytes( 1024 ) : \ ( requestedKeySize < 192 + 8 ) ? bitsToBytes( 1536 ) : \ ( requestedKeySize < 256 + 8 ) ? bitsToBytes( 2048 ) : \ ( requestedKeySize < 384 + 8 ) ? bitsToBytes( 3072 ) : \ 0; int keyDataLength, keyDataChecksum; REQUIRES( isHandleRangeValid( iDHContext ) ); REQUIRES( requestedKeySize >= MIN_PKCSIZE && \ requestedKeySize <= CRYPT_MAX_PKCSIZE ); /* Load the built-in DH key value that corresponds best to the client's requested key size. We allow for a bit of slop to avoid having something like a 1025-bit requested key size lead to the use of a 1536-bit key value. In theory we should probably generate a new DH key each time: status = krnlSendMessage( iDHContext, IMESSAGE_SETATTRIBUTE, ( MESSAGE_CAST ) &requestedKeySize, CRYPT_CTXINFO_KEYSIZE ); if( cryptStatusOK( status ) ) status = krnlSendMessage( iDHContext, IMESSAGE_CTX_GENKEY, NULL, FALSE ); however because the handshake is set up so that the client (rather than the server) chooses the key size we can't actually perform the generation until we're in the middle of the handshake. This means that the server will grind to a halt during each handshake as it generates a new key of whatever size takes the client's fancy (it also leads to a nice potential DoS attack on the server). To avoid this problem we use fixed keys of various common sizes. As late as 2014 Java still can't handle DH keys over 1024 bits (it only allows keys ranging from 512-1024 bits): java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive) so if you need to talk to a system built in Java you need to hardcode the key size below to 1024 bits, the largest size that Java will allow */ switch( actualKeySize ) { case bitsToBytes( 1024 ): keyData = dh1024SSL; keyDataLength = sizeof( dh1024SSL ); keyDataChecksum = dh1024checksum; break; case bitsToBytes( 1536 ): keyData = dh1536SSL; keyDataLength = sizeof( dh1536SSL ); keyDataChecksum = dh1536checksum; break; case bitsToBytes( 2048 ): keyData = dh2048SSL; keyDataLength = sizeof( dh2048SSL ); keyDataChecksum = dh2048checksum; break; case bitsToBytes( 3072 ): default: /* Hier ist der mast zu ende */ keyData = dh3072SSL; keyDataLength = sizeof( dh3072SSL ); keyDataChecksum = dh3072checksum; break; } /* Make sure that the key data hasn't been corrupted */ if( keyDataChecksum != checksumData( keyData, keyDataLength ) ) { DEBUG_DIAG(( "Fixed DH value for %d-bit key has been corrupted", bytesToBits( actualKeySize ) )); retIntError(); } /* Load the fixed DH key into the context */ setMessageData( &msgData, ( MESSAGE_CAST ) keyData, keyDataLength ); return( krnlSendMessage( iDHContext, IMESSAGE_SETATTRIBUTE_S, &msgData, CRYPT_IATTRIBUTE_KEY_SSL ) ); }
value is first truncated to its leftmost nlen bits if nlen is smaller than the hash value bit length before conversion to a bignum. Mathematically, this is equivalent to first converting the value to a bignum and then right-shifting it by hlen - nlen bits, where hlen is the hash length in bits (a more generic way to view the required conversion is 'while( BN_num_bits( hash ) > BN_num_bits( n ) { BN_rshift( hash, 1 ); }'). Finally, we reduce the value modulo n, which is a simple matter of a compare-and-subtract */ CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \ static int hashToBignum( INOUT BIGNUM *bigNum, IN_BUFFER( hashLength ) const void *hash, IN_LENGTH_HASH const int hashLength, const BIGNUM *n ) { const int hlen = bytesToBits( hashLength ); const int nlen = BN_num_bits( n ); int bnStatus = BN_STATUS, status; assert( isWritePtr( bigNum, sizeof( BIGNUM ) ) ); assert( isReadPtr( hash, hashLength ) ); assert( isReadPtr( n, sizeof( BIGNUM ) ) ); REQUIRES( hashLength >= 20 && hashLength <= CRYPT_MAX_HASHSIZE ); /* Convert the hash value into a bignum. We have to be careful when we specify the bounds because, with increasingly smaller probabilities, the leading bytes of the hash value may be zero. The check used here gives one in 4 billion chance of a false positive */ status = importBignum( bigNum, hash, hashLength,
static int readCheckClientCerts( INOUT SESSION_INFO *sessionInfoPtr, INOUT SSL_HANDSHAKE_INFO *handshakeInfo, INOUT STREAM *stream ) { #ifndef CONFIG_SUITEB_TESTS MESSAGE_KEYMGMT_INFO getkeyInfo; MESSAGE_DATA msgData; BYTE certID[ KEYID_SIZE + 8 ]; #endif /* !CONFIG_SUITEB_TESTS */ #ifdef CONFIG_SUITEB int length; #endif /* CONFIG_SUITEB */ int status; /* Read the client certificate chain */ status = readSSLCertChain( sessionInfoPtr, handshakeInfo, stream, &sessionInfoPtr->iKeyexAuthContext, TRUE ); if( cryptStatusError( status ) ) return( status ); /* Make sure that the client certificate is present in our certificate store. Since we've already got a copy of the certificate, we only do a presence check rather than actually fetching the certificate */ #ifndef CONFIG_SUITEB_TESTS setMessageData( &msgData, certID, KEYID_SIZE ); status = krnlSendMessage( sessionInfoPtr->iKeyexAuthContext, IMESSAGE_GETATTRIBUTE_S, &msgData, CRYPT_CERTINFO_FINGERPRINT_SHA1 ); if( cryptStatusOK( status ) ) { setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_CERTID, certID, KEYID_SIZE, NULL, 0, KEYMGMT_FLAG_CHECK_ONLY ); status = krnlSendMessage( sessionInfoPtr->cryptKeyset, IMESSAGE_KEY_GETKEY, &getkeyInfo, KEYMGMT_ITEM_PUBLICKEY ); } if( cryptStatusError( status ) ) { retExt( CRYPT_ERROR_INVALID, ( CRYPT_ERROR_INVALID, SESSION_ERRINFO, "Client certificate is not trusted for authentication " "purposes" ) ); } #endif /* CONFIG_SUITEB_TESTS */ /* Make sure that the key is of the appropriate size for the Suite B security level. At the 128-bit level both P256 and P384 are allowed, at the 256-bit level only P384 is allowed */ #ifdef CONFIG_SUITEB status = krnlSendMessage( sessionInfoPtr->iKeyexAuthContext, IMESSAGE_GETATTRIBUTE, &length, CRYPT_CTXINFO_KEYSIZE ); if( cryptStatusOK( status ) ) { const int suiteBtype = \ sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB; if( suiteBtype == SSL_PFLAG_SUITEB_256 ) { if( length != bitsToBytes( 384 ) ) { retExt( CRYPT_ERROR_INVALID, ( CRYPT_ERROR_INVALID, SESSION_ERRINFO, "Client Suite B certificate uses %d-bit key at " "256-bit security level, should use 384-bit key", bytesToBits( length ) ) ); } } else { if( length != bitsToBytes( 256 ) && \ length != bitsToBytes( 384 ) ) { retExt( CRYPT_ERROR_INVALID, ( CRYPT_ERROR_INVALID, SESSION_ERRINFO, "Client Suite B certificate uses %d-bit key at " "128-bit security level, should use 256- or " "384-bit key", bytesToBits( length ) ) ); } } } #endif /* CONFIG_SUITEB */ return( CRYPT_OK ); }
size). To handle the possibility of a mismatched size we use the following custom conversion function, which applies the conversion rules for transforming the hash value into an integer from FIPS 186-3, "the leftmost min( N, outlen ) bits of Hash( M )" where N = sizeof( q ). Mathematically, this is equivalent to first converting the value to a bignum and then right-shifting it by hlen - nlen bits, where hlen is the hash length in bits (a more generic way to view the required conversion is 'while( BN_num_bits( hash ) > BN_num_bits( n ) { BN_rshift( hash, 1 ); }') */ CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \ static int hashToBignum( INOUT BIGNUM *bigNum, IN_BUFFER( hashLength ) const void *hash, IN_LENGTH_HASH const int hashLength, const BIGNUM *q ) { const int hLen = bytesToBits( hashLength ); const int qLen = BN_num_bits( q ); int bnStatus = BN_STATUS, status; assert( isWritePtr( bigNum, sizeof( BIGNUM ) ) ); assert( isReadPtr( hash, hashLength ) ); assert( isReadPtr( q, sizeof( BIGNUM ) ) ); REQUIRES( hashLength >= 20 && hashLength <= CRYPT_MAX_HASHSIZE ); REQUIRES( qLen >= bytesToBits( 20 ) && \ qLen <= bytesToBits( CRYPT_MAX_PKCSIZE ) ); /* Convert the hash value into a bignum. We have to be careful when we specify the bounds because, with increasingly smaller probabilities, the leading bytes of the hash value may be zero. The check used here gives one in 4 billion chance of a false
static int dlpGenerateComponents( CRYPT_PKCINFO_DLP *dlpKeyInfo, const int keySizeBits, const CRYPT_ALGO_TYPE cryptAlgo ) { CONTEXT_INFO staticContextInfo; PKC_INFO contextData, *pkcInfo = &contextData; int length, status; assert( isWritePtr( dlpKeyInfo, sizeof( CRYPT_PKCINFO_DLP ) ) ); REQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \ keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) ); REQUIRES( cryptAlgo == CRYPT_ALGO_DH || \ cryptAlgo == CRYPT_ALGO_DSA || \ cryptAlgo == CRYPT_ALGO_ELGAMAL ); /* Clear return value */ cryptInitComponents( dlpKeyInfo, FALSE ); /* Generate the key components */ switch( cryptAlgo ) { #ifdef USE_DH case CRYPT_ALGO_DH: status = generateKeyComponents( &staticContextInfo, &contextData, getDHCapability(), keySizeBits ); break; #endif /* USE_DH */ #ifdef USE_DSA case CRYPT_ALGO_DSA: status = generateKeyComponents( &staticContextInfo, &contextData, getDSACapability(), keySizeBits ); break; #endif /* USE_DSA */ #ifdef USE_ELGAMAL case CRYPT_ALGO_ELGAMAL: status = generateKeyComponents( &staticContextInfo, &contextData, getElgamalCapability(), keySizeBits ); break; #endif /* USE_ELGAMAL */ default: retIntError(); } if( cryptStatusError( status ) ) return( status ); /* Extract the newly-generated key components for the caller to use */ dlpKeyInfo->pLen = BN_num_bits( &pkcInfo->dlpParam_p ); length = BN_bn2bin( &pkcInfo->dlpParam_p, dlpKeyInfo->p ); ENSURES( length == bitsToBytes( dlpKeyInfo->pLen ) ); dlpKeyInfo->gLen = BN_num_bits( &pkcInfo->dlpParam_g ); length = BN_bn2bin( &pkcInfo->dlpParam_g, dlpKeyInfo->g ); ENSURES( length == bitsToBytes( dlpKeyInfo->gLen ) ); dlpKeyInfo->qLen = BN_num_bits( &pkcInfo->dlpParam_q ); length = BN_bn2bin( &pkcInfo->dlpParam_q, dlpKeyInfo->q ); ENSURES( length == bitsToBytes( dlpKeyInfo->qLen ) ); dlpKeyInfo->yLen = BN_num_bits( &pkcInfo->dlpParam_y ); length = BN_bn2bin( &pkcInfo->dlpParam_y, dlpKeyInfo->y ); ENSURES( length == bitsToBytes( dlpKeyInfo->yLen ) ); dlpKeyInfo->xLen = BN_num_bits( &pkcInfo->dlpParam_x ); length = BN_bn2bin( &pkcInfo->dlpParam_x, dlpKeyInfo->x ); ENSURES( length == bitsToBytes( dlpKeyInfo->xLen ) ); staticDestroyContext( &staticContextInfo ); return( status ); }