/* PUBLIC FUNCTION DEFINITIONS **********************************************/ CsrUint8 getMessageType( WpsBuffer *pIn ) { CsrUint8 result = 0; WpsBuffer value; do { if( WPS_VERSION != getDataElement( pIn, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "getDataElement(): Version missing" )); break; } if( !checkVersion( &value ) ) { sme_trace_info((TR_SECURITY_LIB, "checkVersion(): version not supported" )); break; } if( WPS_MESSAGE_TYPE != getDataElement( pIn, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "getDataElement(): Message Type missing" )); break; } /* Everything OK if no break by this point. Finally check the length of the * Message Type data element before setting return value */ if( value.size == 1 ) { result = value.pStart[0]; } } while( 0 ); return result; }
double AverageOnGrid::getGridElement( const unsigned& ipoint, const unsigned& jelement ) const { if( noAverage() ) return getDataElement( nper*ipoint + jelement); if( jelement>=(nper-(dimension+1)) ) return getDataElement( nper*ipoint + jelement ); if( noderiv ) return getDataElement( nper*ipoint+jelement ) / getDataElement( nper*(1+ipoint) - 1); double rdenom = 1.0; if( fabs(getDataElement( nper*(ipoint+1) -(dimension+1) ))>epsilon ) rdenom = 1. / getDataElement( nper*(ipoint+1) - (dimension+1) ); unsigned jderiv = jelement%(1+dimension); if( jderiv==0 ) return rdenom*getDataElement( nper*ipoint+jelement ); unsigned jfloor = std::floor( jelement / (1+dimension) ); return rdenom*getDataElement( nper*ipoint+jelement ) - rdenom*rdenom*getDataElement(nper*ipoint+jfloor)*getDataElement(nper*(ipoint+1) - (dimension+1) + jderiv); }
DataElement* createRasterElement(const char* pName, RasterElementArgs args) { if (pName == NULL || args.location > 2) { setLastError(SIMPLE_BAD_PARAMS); return NULL; } // Check for an existing element with the name if (getDataElement(pName, TypeConverter::toString<RasterElement>(), 0) != NULL) { setLastError(SIMPLE_EXISTS); return NULL; } RasterElement* pElement = RasterUtilities::createRasterElement(std::string(pName), args.numRows, args.numColumns, args.numBands, static_cast<EncodingTypeEnum>(args.encodingType), static_cast<InterleaveFormatTypeEnum>(args.interleaveFormat), args.location != 2, args.pParent); if (pElement == NULL) { switch (args.location) { case 0: pElement = RasterUtilities::createRasterElement(std::string(pName), args.numRows, args.numColumns, args.numBands, static_cast<EncodingTypeEnum>(args.encodingType), static_cast<InterleaveFormatTypeEnum>(args.interleaveFormat), false, args.pParent); if (pElement == NULL) { setLastError(SIMPLE_OTHER_FAILURE); return NULL; } break; case 1: setLastError(SIMPLE_NO_MEM); return NULL; case 2: setLastError(SIMPLE_OTHER_FAILURE); return NULL; default: setLastError(SIMPLE_BAD_PARAMS); return NULL; } } if (args.pBadValues != NULL && args.numBadValues > 0) { RasterDataDescriptor* pDesc = static_cast<RasterDataDescriptor*>(pElement->getDataDescriptor()); if (pDesc != NULL) { std::vector<int> badValues; badValues.reserve(args.numBadValues); for (uint32_t idx = 0; idx < args.numBadValues; ++idx) { badValues.push_back(args.pBadValues[idx]); } pDesc->setBadValues(badValues); // set on the statistics objects const std::vector<DimensionDescriptor>& allBands = pDesc->getBands(); for (std::vector<DimensionDescriptor>::const_iterator band = allBands.begin(); band != allBands.end(); ++band) { if (band->isValid()) { Statistics* pStats = pElement->getStatistics(*band); if (pStats != NULL) { pStats->setBadValues(badValues); } } } pElement->updateData(); } } setLastError(SIMPLE_NO_ERROR); return pElement; }
static Template parse(const dotX39::Node& node, const std::vector<Ressource>& ressourceList) { auto tmp = Template(); tmp.qualifier = node.getName(); #pragma region Argument Parsing for (int i = 0; i < node.getArgumentCount(); i++) { const dotX39::Data* arg = node.getArgument(i); if (arg->getName().compare("path") == 0) { if (arg->getType() != dotX39::DataTypes::STRING) { std::cerr << std::string("the nodes '").append(tmp.qualifier).append("' 'path' argument should be STRING") << std::endl; throw Exceptions::InvalidTypeStructureException(); } tmp.filePath = std::string(Globals::getInstance().basePath.templates).append(static_cast<const dotX39::DataString*>(arg)->getDataAsString()); } else if (arg->getName().compare("fileName") == 0) { if (arg->getType() != dotX39::DataTypes::STRING) { std::cerr << std::string("the nodes '").append(tmp.qualifier).append("' 'fileName' argument should be STRING") << std::endl; throw Exceptions::InvalidTypeStructureException(); } tmp.outputFileName = std::string(static_cast<const dotX39::DataString*>(arg)->getDataAsString()); } else if (arg->getName().compare("fileExtension") == 0) { if (arg->getType() != dotX39::DataTypes::STRING) { std::cerr << std::string("the nodes '").append(tmp.qualifier).append("' 'fileExtension' argument should be STRING") << std::endl; throw Exceptions::InvalidTypeStructureException(); } tmp.outputFileExtension = std::string(static_cast<const dotX39::DataString*>(arg)->getDataAsString()); } else { if (Globals::getInstance().verbosity) std::cout << std::string("the node '").append(tmp.qualifier).append("' contains the unknown argument '").append(arg->getName()).append("', ignored.") << std::endl; } } #pragma endregion #pragma region Data Parsing for (int i = 0; i < node.getDataCount(); i++) { const dotX39::Data* data = node.getData(i); if (data->getName().compare("ressources") == 0) { if (data->getType() != dotX39::DataTypes::ARRAY) { std::cerr << std::string("the nodes '").append(tmp.qualifier).append("' 'ressources' argument should be ARRAY") << std::endl; throw Exceptions::InvalidTypeStructureException(); } auto tmpDataArray = static_cast<const dotX39::DataArray*>(data); //We want to validate ALL ressources here so lets create an error counter instead of throwing an exception instantly size_t errCount = 0; for (int j = 0; j < tmpDataArray->getDataCount(); j++) { auto data = tmpDataArray->getDataElement(j); if (data->getType() != dotX39::DataTypes::STRING) { std::cerr << std::string("the nodes '").append(tmp.qualifier).append("' 'ressource' argument should be ARRAY with just STRINGs") << std::endl; throw Exceptions::InvalidTypeStructureException(); } //Find the ressource in available ressources and push it to the templates ressource list bool flag = false; auto ressourceName = static_cast<const dotX39::DataString*>(data)->getDataAsString(); for (auto& it : ressourceList) { if (it.getQualifier().compare(ressourceName) == 0) { tmp.ressources.push_back(it); flag = true; break; } } if (!flag) { errCount++; std::cerr << "Ressource '" << ressourceName << "' is not existing (template: '" << tmp.qualifier << "')" << std::endl; } } //if we did found errors, throw the invalid_argument exception if (errCount > 0) throw std::invalid_argument("Some Ressources are not existing for a Template"); } else { if (Globals::getInstance().verbosity) std::cout << std::string("the node '").append(tmp.qualifier).append("' contains the unknown argument '").append(data->getName()).append("', ignored.") << std::endl; } } #pragma endregion #pragma region Node Parsing for (int i = 0; i < node.getNodeCount(); i++) { auto subnode = node.getNode(i); if (subnode->getName().compare("templateKeywords") == 0) { for (int j = 0; j < subnode->getDataCount(); j++) { auto data = subnode->getData(j); if (data->getType() != dotX39::DataTypes::STRING) { std::cerr << std::string("the nodes '").append(tmp.qualifier).append("' subnodes '").append(subnode->getName()).append("' data datatypes should be STRING") << std::endl; throw Exceptions::InvalidTypeStructureException(); } auto templateKeyword = TemplateKeyword::parse(*static_cast<const dotX39::DataString*>(data)); tmp.keywords.templates.push_back(templateKeyword); } } else if (subnode->getName().compare("replacementKeywords") == 0) { for (int j = 0; j < subnode->getDataCount(); j++) { auto data = subnode->getData(j); if (data->getType() != dotX39::DataTypes::ARRAY) { std::cerr << std::string("the nodes '").append(tmp.qualifier).append("' subnodes '").append(subnode->getName()).append("' data datatypes should be ARRAY") << std::endl; throw Exceptions::InvalidTypeStructureException(); } tmp.keywords.replacements.push_back(ReplacementKeyword::parse(*static_cast<const dotX39::DataArray*>(data))); } } else { if (Globals::getInstance().verbosity) std::cout << std::string("the node '").append(tmp.qualifier).append("' contains the unknown node '").append(subnode->getName()).append("', ignored.") << std::endl; } } #pragma endregion if (tmp.filePath.empty()) { std::cerr << std::string("the node '").append(tmp.getQualifier()).append("' has no path argument provided") << std::endl; exit(-1); } std::ifstream stream = std::ifstream(std::string(tmp.filePath).c_str()); if (!stream.is_open() || !stream.good()) { auto errMsg = std::string("Could not read file: ").append(tmp.filePath); std::cerr << errMsg << std::endl; throw std::runtime_error(errMsg); } char s[256]; while (!stream.eof()) { memset(s, 0, sizeof(s)); stream.read(s, 255); tmp.fileData.append(s); } stream.close(); return tmp; }
CsrBool parseCredential( CsrWpsContext *pCtx, WpsBuffer *pCredential, CsrInt32 credentialCount ) { WpsBuffer value; CsrUint32 id; CsrBool result = FALSE; do { if(WPS_NETWORK_INDEX != getDataElement(pCredential, &value)) { sme_trace_info((TR_SECURITY_LIB, "Encrypted Settings Data: required Network Index missing")); break; } if(WPS_SSID != getDataElement(pCredential, &value)) { sme_trace_info((TR_SECURITY_LIB, "Encrypted Settings Data: required SSID missing")); break; } if(credentialCount != 0 && CsrMemCmp(value.pStart, pCtx->securityContext->setupData.ssid, value.size)) { /* Terminate the parse early successfully if the SSID does not match */ result = TRUE; break; } sme_trace_info((TR_SECURITY_LIB, "Match found for SSID %s", pCtx->securityContext->setupData.ssid)); /* Remember the SSID for the final profile generation */ CsrMemCpy(pCtx->ssid, value.pStart, value.size); if(WPS_AUTHENTICATION_TYPE != getDataElement(pCredential, &value)) { sme_trace_info((TR_SECURITY_LIB, "Encrypted Settings Data: required Authentication Type missing")); break; } sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "Authentication type", value.pStart, value.size)); if(value.size == 2) { pCtx->authenticationType = value.pStart[0] << 8; pCtx->authenticationType |= value.pStart[1]; } else { sme_trace_info((TR_SECURITY_LIB, "Authentication Type incorrect size")); pCtx->authenticationType = 0; } if(WPS_ENCRYPTION_TYPE != getDataElement(pCredential, &value)) { sme_trace_info((TR_SECURITY_LIB, "Encrypted Settings Data: required Encryption Type missing")); break; } sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "Encryption type", value.pStart, value.size)); if(value.size == 2) { pCtx->encryptionType = value.pStart[0] << 8; pCtx->encryptionType |= value.pStart[1]; } else { sme_trace_info((TR_SECURITY_LIB, "Encryption Type incorrect size")); pCtx->encryptionType = 0; } id = getDataElement(pCredential, &value); if(WPS_NETWORK_KEY_INDEX != id) { sme_trace_info((TR_SECURITY_LIB, "Encrypted Settings Data: optional Network Key Index missing")); /* Default to network key index 1 */ pCtx->networkKeyIndex = 1; } else { if(value.size == 1 && value.pStart[0] >= 1 && value.pStart[0] <= 4) { pCtx->networkKeyIndex = value.pStart[0]; } id = getDataElement(pCredential, &value); } if(WPS_NETWORK_KEY != id) { sme_trace_info((TR_SECURITY_LIB, "Encrypted Settings Data: required Network Key missing (ignored)")); pCtx->networkKeyLength = 0; } else { if ((CsrUint16) value.size > sizeof(pCtx->networkKey)) { sme_trace_info((TR_SECURITY_LIB, "Network key too big")); break; } pCtx->networkKeyLength = (CsrUint16) value.size; CsrMemCpy(pCtx->networkKey, value.pStart, value.size); id = getDataElement(pCredential, &value); } if(WPS_MAC_ADDRESS != id) { sme_trace_info((TR_SECURITY_LIB, "Encrypted Settings Data: required MAC Address missing")); break; } /* Check for any optional data elements */ for(id = getDataElement(pCredential, &value); id != 0; id = getDataElement(pCredential, &value)) { sme_trace_info((TR_SECURITY_LIB, "Encrypted Settings Data: Optional (%04x)", id)); } /* Everything present and correct if no break by this point */ result = TRUE; } while(0); return result; }
void parseEncryptedSettingsM8(CsrWpsContext *pCtx) { WpsBuffer value; CsrUint32 id; CsrInt32 credentialCount = 0; CsrUint8 digest[WPS_SHA256_DIGEST_LENGTH]; sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS Encrypted Settings IV", pCtx->encryptedSettings.pStart, WPS_IV_LENGTH)); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS Encrypted Settings", &pCtx->encryptedSettings.pStart[WPS_IV_LENGTH], pCtx->encryptedSettings.size - WPS_IV_LENGTH)); initBuffer(&pCtx->decryptedSettings, (CsrUint8 *)CsrPmalloc(1000), 1000); CsrCryptoAes128CbcDecrypt(pCtx->keyWrapKey, pCtx->encryptedSettings.pStart, &pCtx->encryptedSettings.pStart[WPS_IV_LENGTH], pCtx->encryptedSettings.size - WPS_IV_LENGTH, pCtx->decryptedSettings.pStart, &pCtx->decryptedSettings.size, PAD_MODE_PKCS7); sme_trace_info((TR_SECURITY_LIB, "Decrypted %d bytes from Encrypted Settings", pCtx->decryptedSettings.size)); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS Decrypted Settings", pCtx->decryptedSettings.pStart, pCtx->decryptedSettings.size)); if(WPS_CREDENTIAL != getDataElement(&pCtx->decryptedSettings, &value)) { sme_trace_info((TR_SECURITY_LIB, "Encrypted Settings Data: required Credential missing")); pCtx->result = FALSE; freeBuffer(&pCtx->decryptedSettings); return; } if(!parseCredential(pCtx, &value, credentialCount)) { sme_trace_info((TR_SECURITY_LIB, "Encrypted Settings Data: Credential parse bad")); } credentialCount++; /* Check for any non-required optional data elements before final Authenticator data element */ id = getDataElement(&pCtx->decryptedSettings, &value); while(WPS_CREDENTIAL == id) { if(!parseCredential(pCtx, &value, credentialCount)) { sme_trace_info((TR_SECURITY_LIB, "Encrypted Settings Data: Credential parse bad")); } credentialCount++; id = getDataElement(&pCtx->decryptedSettings, &value); } while(id != 0 && id != WPS_KEY_WRAP_AUTHENTICATOR) { sme_trace_info((TR_SECURITY_LIB, "Encrypted Settings Data: Non-required optional (%04x)", id)); id = getDataElement(&pCtx->decryptedSettings, &value); } if(WPS_KEY_WRAP_AUTHENTICATOR != id) { sme_trace_info((TR_SECURITY_LIB, "Encrypted Settings Data: Key Wrap Authenticator missing")); pCtx->result = FALSE; freeBuffer(&pCtx->decryptedSettings); return; } pCtx->rxAuthenticator = value.pStart; /* Do not include the 12 byte key wrap authenticator element in the calculation */ pCtx->decryptedSettings.size -= WPS_TL_LENGTH + WPS_AUTHENTICATOR_LENGTH; CsrCryptoHmacSha256(pCtx->authKey, sizeof(pCtx->authKey), pCtx->decryptedSettings.pStart, pCtx->decryptedSettings.size, digest); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS authenticator", digest, WPS_AUTHENTICATOR_LENGTH)); pCtx->decryptedSettings.size += WPS_TL_LENGTH + WPS_AUTHENTICATOR_LENGTH; if(CsrMemCmp(digest, pCtx->rxAuthenticator, WPS_AUTHENTICATOR_LENGTH)) { sme_trace_info((TR_SECURITY_LIB, "Encrypted Settings Data: Key Wrap Authenticator bad")); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS authenticator", pCtx->rxAuthenticator, WPS_AUTHENTICATOR_LENGTH)); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS computed authenticator", digest, WPS_AUTHENTICATOR_LENGTH)); pCtx->result = FALSE; freeBuffer(&pCtx->decryptedSettings); return; } /* Everything present and correct if no break by this point */ pCtx->securityContext->callbacks.wpsDone(pCtx->securityContext->externalContext, TRUE, pCtx->authenticationType, pCtx->encryptionType, pCtx->networkKey, pCtx->networkKeyLength, pCtx->networkKeyIndex, pCtx->ssid); freeBuffer(&pCtx->decryptedSettings); }
void parseM8( CsrWpsContext *pCtx ) { WpsBuffer value; CsrUint32 id; CsrUint8 digest[WPS_SHA256_DIGEST_LENGTH]; do { if(WPS_ENROLLEE_NONCE != getDataElement(&pCtx->in, &value)) { sme_trace_info((TR_SECURITY_LIB, "M8: required Enrollee Nonce missing")); pCtx->result = FALSE; break; } if(WPS_ENCRYPTED_SETTINGS != getDataElement(&pCtx->in, &pCtx->encryptedSettings)) { sme_trace_info((TR_SECURITY_LIB, "M8: required Encrypted Settings missing")); pCtx->result = FALSE; break; } /* Check for any non-required optional data elements before final Authenticator data element */ for( id = getDataElement(&pCtx->in, &value); id != 0 && id != WPS_AUTHENTICATOR; id = getDataElement(&pCtx->in, &value)) { sme_trace_info((TR_SECURITY_LIB, "M8: Non-required optional (%04x)", id)); } if(WPS_AUTHENTICATOR != id) { sme_trace_info((TR_SECURITY_LIB, "M8: Authenticator missing")); pCtx->result = FALSE; break; } } while (0); if (pCtx->result == FALSE) { return; } pCtx->rxAuthenticator = value.pStart; /* Do not include the 12 byte authenticator element in the current message */ /* Compute Authenticator */ pCtx->in.size -= WPS_TL_LENGTH + WPS_AUTHENTICATOR_LENGTH; pCtx->message = (CsrUint8 *)CsrPmalloc(pCtx->out.size + pCtx->in.size); CsrMemCpy(pCtx->message, pCtx->out.pStart, pCtx->out.size); CsrMemCpy(pCtx->message + pCtx->out.size, pCtx->in.pStart, pCtx->in.size); CsrCryptoHmacSha256(pCtx->authKey, sizeof(pCtx->authKey), pCtx->message, pCtx->out.size + pCtx->in.size, digest); CsrPfree(pCtx->message); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS authenticator", digest, WPS_AUTHENTICATOR_LENGTH)); pCtx->in.size += WPS_TL_LENGTH + WPS_AUTHENTICATOR_LENGTH; if(CsrMemCmp(pCtx->rxAuthenticator, digest, WPS_AUTHENTICATOR_LENGTH)) { sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS Authenticator error", pCtx->rxAuthenticator, WPS_AUTHENTICATOR_LENGTH)); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS computed authenticator", digest, WPS_AUTHENTICATOR_LENGTH)); sme_trace_info((TR_SECURITY_LIB, "WPS M8 Authenticator BAD")); pCtx->result = FALSE; return; } parseEncryptedSettingsM8(pCtx); if(pCtx->result == FALSE) { sme_trace_info((TR_SECURITY_LIB, "WPS Encrypted Settings parse failed")); } /* Everything present and correct if no break by this point */ }
void parseEncryptedSettingsM6(CsrWpsContext *pCtx) { CsrUint8 iv[WPS_IV_LENGTH]; WpsBuffer value; CsrUint32 id; CsrUint8 digest[WPS_SHA256_DIGEST_LENGTH]; sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS Encrypted Settings IV", pCtx->encryptedSettings.pStart, WPS_IV_LENGTH)); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS Encrypted Settings", &pCtx->encryptedSettings.pStart[WPS_IV_LENGTH], pCtx->encryptedSettings.size - WPS_IV_LENGTH)); CsrMemCpy(iv, pCtx->encryptedSettings.pStart, WPS_IV_LENGTH); initBuffer(&pCtx->decryptedSettings, (CsrUint8 *)CsrPmalloc(1000), 1000); CsrCryptoAes128CbcDecrypt(pCtx->keyWrapKey, iv, &pCtx->encryptedSettings.pStart[WPS_IV_LENGTH], pCtx->encryptedSettings.size - WPS_IV_LENGTH, pCtx->decryptedSettings.pStart, &pCtx->decryptedSettings.size, PAD_MODE_PKCS7); sme_trace_info((TR_SECURITY_LIB, "Decrypted %d bytes from Encrypted Settings", pCtx->decryptedSettings.size)); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS Decrypted Settings", pCtx->decryptedSettings.pStart, pCtx->decryptedSettings.size)); if(WPS_R_SNONCE2 != getDataElement( &pCtx->decryptedSettings, &pCtx->rSNonce2)) { sme_trace_info((TR_SECURITY_LIB, "Encrypted Settings Data: required R-SNONCE2 missing")); pCtx->result = FALSE; freeBuffer(&pCtx->decryptedSettings); return; } /* Check for any non-required optional data elements before final authenticator data element */ for(id = getDataElement(&pCtx->decryptedSettings, &value); id != 0 && id != WPS_KEY_WRAP_AUTHENTICATOR; id = getDataElement(&pCtx->decryptedSettings, &value)) { sme_trace_info((TR_SECURITY_LIB, "Encrypted Settings Data: Non-required optional (%04x)", id)); } if(WPS_KEY_WRAP_AUTHENTICATOR != id) { sme_trace_info((TR_SECURITY_LIB, "Encrypted Settings Data: Key Wrap Authenticator missing")); pCtx->result = FALSE; freeBuffer(&pCtx->decryptedSettings); return; } pCtx->rxAuthenticator = value.pStart; /* Do not include the 12 byte key wrap authenticator element in the calculation */ pCtx->decryptedSettings.size -= WPS_TL_LENGTH + WPS_AUTHENTICATOR_LENGTH; CsrCryptoHmacSha256(pCtx->authKey, sizeof(pCtx->authKey), pCtx->decryptedSettings.pStart, pCtx->decryptedSettings.size, digest); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS authenticator", digest, WPS_AUTHENTICATOR_LENGTH)); pCtx->decryptedSettings.size += WPS_TL_LENGTH + WPS_AUTHENTICATOR_LENGTH; if(CsrMemCmp(digest, pCtx->rxAuthenticator, WPS_AUTHENTICATOR_LENGTH)) { sme_trace_info((TR_SECURITY_LIB, "Encrypted Settings Data: Key Wrap Authenticator bad")); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS authenticator", pCtx->rxAuthenticator, WPS_AUTHENTICATOR_LENGTH)); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS computed authenticator", digest, WPS_AUTHENTICATOR_LENGTH)); pCtx->result = FALSE; freeBuffer(&pCtx->decryptedSettings); return; } /* The R-SNonce2 is now decoded, so R-HASH2 can be checked */ /* The E-Hash is the HMAC-SHA256 of the concatenation of a secret nonce, PSK, the Enrollee Public Key and the Registrar Public Key, keyed with AuthKey. */ pCtx->message = (CsrUint8 *)CsrPmalloc(2 * WPS_NONCE_LENGTH + sizeof(pCtx->ePubKey) + sizeof(pCtx->rPubKey)); CsrMemCpy(pCtx->message, pCtx->rSNonce2.pStart, WPS_NONCE_LENGTH); CsrMemCpy(pCtx->message + WPS_NONCE_LENGTH, pCtx->psk2, WPS_NONCE_LENGTH); CsrMemCpy(pCtx->message + 2 * WPS_NONCE_LENGTH, pCtx->ePubKey, sizeof(pCtx->ePubKey)); CsrMemCpy(pCtx->message + 2 * WPS_NONCE_LENGTH + sizeof(pCtx->ePubKey), pCtx->rPubKey, sizeof(pCtx->rPubKey)); CsrCryptoHmacSha256(pCtx->authKey, WPS_SHA256_DIGEST_LENGTH, pCtx->message, 2 * WPS_NONCE_LENGTH + sizeof(pCtx->ePubKey) + sizeof(pCtx->rPubKey), digest); CsrPfree(pCtx->message); if(CsrMemCmp(digest, pCtx->rHash2, WPS_SHA256_DIGEST_LENGTH)) { sme_trace_info((TR_SECURITY_LIB, "R-HASH2 verification failed")); pCtx->result = FALSE; } freeBuffer(&pCtx->decryptedSettings); /* Everything present and correct if no break by this point */ }
void parseM2( CsrWpsContext *pCtx ) { WpsBuffer value; CsrUint32 id; CsrBool result = FALSE; CsrUint8 digest[WPS_SHA256_DIGEST_LENGTH]; do { if( WPS_ENROLLEE_NONCE != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required Enrollee Nonce missing" )); break; } if( WPS_REGISTRAR_NONCE != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required Registrar Nonce missing" )); break; } /* Check incoming length against expected length? */ CsrMemCpy( pCtx->rNonce, value.pStart, sizeof( pCtx->rNonce ) ); if( WPS_UUID_R != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required UUID-R missing" )); break; } if( WPS_PUBLIC_KEY != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required Public Key missing" )); break; } /* Check incoming length against expected length? */ CsrMemCpy( pCtx->rPubKey, value.pStart, sizeof( pCtx->rPubKey ) ); if( WPS_AUTHENTICATION_TYPE_FLAGS != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required Authentication Type Flags missing" )); break; } if( WPS_ENCRYPTION_TYPE_FLAGS != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required Encryption Type Flags missing" )); break; } if( WPS_CONNECTION_TYPE_FLAGS != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required Connection Type Flags missing" )); break; } if( WPS_CONFIG_METHODS != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required Config Methods missing" )); break; } if( WPS_MANUFACTURER != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required Manufacturer missing" )); break; } if( WPS_MODEL_NAME != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required Model Name missing" )); break; } if( WPS_MODEL_NUMBER != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required Model Number missing" )); break; } if( WPS_SERIAL_NUMBER != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required Serial Number missing" )); break; } if( WPS_PRIMARY_DEVICE_TYPE != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required Primary Device Type missing" )); break; } if( WPS_DEVICE_NAME != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required Device Name missing" )); break; } if( WPS_RF_BANDS != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required RF Bands missing" )); break; } if( WPS_ASSOCIATION_STATE != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required Association State missing" )); break; } if( WPS_CONFIGURATION_ERROR != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required Configuration Error missing" )); break; } if( WPS_DEVICE_PASSWORD_ID != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required Device Password ID missing" )); break; } if( WPS_OS_VERSION_ID != getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: required OS Version ID missing" )); break; } /* Check for any non-required optional data elements before final Authenticator data element */ for( id = getDataElement( &pCtx->in, &value ); id != 0 && id != WPS_AUTHENTICATOR; id = getDataElement( &pCtx->in, &value ) ) { sme_trace_info((TR_SECURITY_LIB, "M2: Non-required optional (%04x)", id )); } if( WPS_AUTHENTICATOR != id ) { sme_trace_info((TR_SECURITY_LIB, "M2: Authenticator missing" )); break; } pCtx->rxAuthenticator = value.pStart; result = TRUE; } while (0); if (result == FALSE) { pCtx->result = FALSE; return; } computeSessionKeys (pCtx); /* Session keys must be derived before AuthKey is used to verify authenticator */ /* Do not include the 12 byte authenticator element in the current message */ pCtx->in.size -= WPS_TL_LENGTH + WPS_AUTHENTICATOR_LENGTH; pCtx->message = (CsrUint8 *) CsrPmalloc(pCtx->out.size + pCtx->in.size); CsrMemCpy(pCtx->message, pCtx->out.pStart, pCtx->out.size); CsrMemCpy(pCtx->message + pCtx->out.size, pCtx->in.pStart, pCtx->in.size); CsrCryptoHmacSha256(pCtx->authKey, sizeof(pCtx->authKey), pCtx->message, pCtx->out.size + pCtx->in.size, digest); CsrPfree(pCtx->message); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS authenticator", digest, WPS_AUTHENTICATOR_LENGTH)); pCtx->in.size += WPS_TL_LENGTH + WPS_AUTHENTICATOR_LENGTH; if(CsrMemCmp(digest, pCtx->rxAuthenticator, WPS_AUTHENTICATOR_LENGTH)) { sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS Authenticator error", pCtx->rxAuthenticator, WPS_AUTHENTICATOR_LENGTH)); sme_trace_hex((TR_SECURITY_LIB, TR_LVL_INFO, "WPS computed authenticator", digest, WPS_AUTHENTICATOR_LENGTH)); sme_trace_info((TR_SECURITY_LIB, "WPS M2 Authenticator BAD")); pCtx->result = FALSE; } else { /* Everything present and correct at this point */ pCtx->result = TRUE; } }