Embed:
(wiki syntax)
Show/hide line numbers
oid.c
Go to the documentation of this file.
00001 /** 00002 * @file oid.c 00003 * @brief OID (Object Identifier) 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneCrypto Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00026 * @version 1.7.6 00027 **/ 00028 00029 //Switch to the appropriate trace level 00030 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL 00031 00032 //Dependencies 00033 #include <string.h> 00034 #include <ctype.h> 00035 #include "crypto.h" 00036 #include "oid.h" 00037 #include "debug.h" 00038 00039 //Check crypto library configuration 00040 #if (OID_SUPPORT == ENABLED) 00041 00042 00043 /** 00044 * @brief Check whether the specified object identifier is valid 00045 * @param[in] oid Pointer to the object identifier 00046 * @param[in] oidLen Length of the OID, in bytes 00047 * @return Error code 00048 **/ 00049 00050 error_t oidCheck(const uint8_t *oid, size_t oidLen) 00051 { 00052 size_t i; 00053 size_t n; 00054 00055 //Check parameters 00056 if(oid == NULL) 00057 return ERROR_INVALID_PARAMETER; 00058 00059 //Check the length of the OID 00060 if(oidLen == 0) 00061 { 00062 //Report an error 00063 return ERROR_INVALID_SYNTAX; 00064 } 00065 else if(oidLen > 1) 00066 { 00067 //Parse the object identifier 00068 for(i = 1, n = 2; i < oidLen; i++) 00069 { 00070 //Update the total number of nodes 00071 if(!(oid[i] & OID_MORE_FLAG)) 00072 n++; 00073 00074 //SNMP limits object identifier values to a maximum of 128 nodes 00075 if(n > 128) 00076 return ERROR_INVALID_SYNTAX; 00077 } 00078 00079 //Ensure that the last sub-identifier is valid 00080 if(oid[oidLen - 1] & OID_MORE_FLAG) 00081 return ERROR_INVALID_SYNTAX; 00082 } 00083 00084 //The specified OID is valid 00085 return NO_ERROR; 00086 } 00087 00088 00089 /** 00090 * @brief Compare object identifiers 00091 * @param[in] oid1 Pointer the first OID 00092 * @param[in] oidLen1 Length of the first OID, in bytes 00093 * @param[in] oid2 Pointer the second OID 00094 * @param[in] oidLen2 Length of the second OID, in bytes 00095 * @return Comparison result 00096 * @retval 0 Objects identifiers are equal 00097 * @retval -1 The first OID lexicographically precedes the second OID 00098 * @retval 1 The second OID lexicographically precedes the first OID 00099 **/ 00100 00101 int_t oidComp(const uint8_t *oid1, size_t oidLen1, 00102 const uint8_t *oid2, size_t oidLen2) 00103 { 00104 size_t i; 00105 00106 //Perform lexicographical comparison 00107 for(i = 0; i < oidLen1 && i < oidLen2; i++) 00108 { 00109 //Compare current byte 00110 if(oid1[i] < oid2[i]) 00111 return -1; 00112 else if(oid1[i] > oid2[i]) 00113 return 1; 00114 } 00115 00116 //Compare length 00117 if(oidLen1 < oidLen2) 00118 return -1; 00119 else if(oidLen1 > oidLen2) 00120 return 1; 00121 00122 //Object identifiers are equal 00123 return 0; 00124 } 00125 00126 00127 /** 00128 * @brief Encode OID sub-identifier 00129 * @param[in] oid Pointer to the object identifier 00130 * @param[in] maxOidLen Maximum number of bytes the OID can hold 00131 * @param[in,out] pos Offset where to write the sub-identifier 00132 * @param[in] value Value of the sub-identifier 00133 * @return Error code 00134 **/ 00135 00136 error_t oidEncodeSubIdentifier(uint8_t *oid, 00137 size_t maxOidLen, size_t *pos, uint32_t value) 00138 { 00139 size_t i; 00140 size_t n; 00141 uint8_t temp[5]; 00142 00143 //Encode the first byte of the sub-identifier 00144 temp[0] = value & OID_VALUE_MASK; 00145 //Shift the value to the right 00146 value >>= 7; 00147 00148 //Encode the remaining bytes 00149 for(n = 1; value != 0; n++) 00150 { 00151 //Encode current byte 00152 temp[n] = OID_MORE_FLAG | (value & OID_VALUE_MASK); 00153 //Shift the value to the right 00154 value >>= 7; 00155 } 00156 00157 //Sanity check 00158 if((*pos + n) > maxOidLen) 00159 return ERROR_BUFFER_OVERFLOW; 00160 00161 //Write the current sub-identifier 00162 for(i = 0; i < n; i++) 00163 oid[*pos + i] = temp[n - i - 1]; 00164 00165 //Update offset value 00166 *pos += n; 00167 00168 //Successful processing 00169 return NO_ERROR; 00170 } 00171 00172 00173 /** 00174 * @brief Decode OID sub-identifier 00175 * @param[in] oid Pointer to the object identifier 00176 * @param[in] oidLen Length of the OID, in bytes 00177 * @param[in,out] pos Offset where to read the sub-identifier 00178 * @param[out] value Value of the sub-identifier 00179 * @return Error code 00180 **/ 00181 00182 error_t oidDecodeSubIdentifier(const uint8_t *oid, 00183 size_t oidLen, size_t *pos, uint32_t *value) 00184 { 00185 size_t i; 00186 00187 //Initialize the value of the sub-identifier 00188 *value = 0; 00189 00190 //Read the OID until the last byte of the sub-identifier is found 00191 for(i = *pos; i < oidLen; i++) 00192 { 00193 //Shift the value to the left 00194 *value <<= 7; 00195 //Update value of the sub-identifier 00196 *value |= oid[i] & OID_VALUE_MASK; 00197 00198 //Bit b8 is set to zero to indicate the last byte 00199 if(!(oid[i] & OID_MORE_FLAG)) 00200 { 00201 //Update offset value 00202 *pos = i + 1; 00203 //Successful processing 00204 return NO_ERROR; 00205 } 00206 } 00207 00208 //The specified OID is not valid 00209 return ERROR_INVALID_SYNTAX; 00210 } 00211 00212 00213 /** 00214 * @brief Convert a string representation of an OID to a binary OID 00215 * @param[in] str NULL-terminated string representing the OID 00216 * @param[out] oid Object identifier 00217 * @param[in] maxOidLen Maximum number of bytes the OID can hold 00218 * @param[out] oidLen Length of the object identifier 00219 * @return Error code 00220 **/ 00221 00222 error_t oidFromString(const char_t *str, 00223 uint8_t *oid, size_t maxOidLen, size_t *oidLen) 00224 { 00225 error_t error; 00226 size_t i; 00227 size_t j; 00228 size_t n; 00229 uint32_t value; 00230 uint8_t temp[5]; 00231 00232 //Reset the length of the OID 00233 *oidLen = 0; 00234 00235 //Number of nodes 00236 i = 0; 00237 //Initialize the value of the sub-identifier 00238 value = 0; 00239 00240 //Parse input string 00241 while(1) 00242 { 00243 //Digit found? 00244 if(isdigit((uint8_t) *str)) 00245 { 00246 //Update the value of the sub-identifier 00247 value = (value * 10) + (*str - '0'); 00248 } 00249 //Separator or end of string found? 00250 else if(*str == '.' || *str == '\0') 00251 { 00252 //First node? 00253 if(i == 0) 00254 { 00255 //Check value 00256 if(value > 6) 00257 { 00258 //The conversion failed 00259 error = ERROR_INVALID_SYNTAX; 00260 break; 00261 } 00262 00263 //Encode the first sub-identifier 00264 temp[0] = value * 40; 00265 //Prepare to decode the next node 00266 value = 0; 00267 //Do not write current sub-identifier yet 00268 n = 0; 00269 } 00270 //Second node? 00271 else if(i == 1) 00272 { 00273 //Check value 00274 if(value > 39) 00275 { 00276 //The conversion failed 00277 error = ERROR_INVALID_SYNTAX; 00278 break; 00279 } 00280 00281 //Encode the second sub-identifier 00282 temp[0] |= value; 00283 //Prepare to decode the next node 00284 value = 0; 00285 //Write the first two sub-identifiers 00286 n = 1; 00287 } 00288 //Remaining nodes? 00289 else 00290 { 00291 //Encode the first byte of the sub-identifier 00292 temp[0] = value & OID_VALUE_MASK; 00293 //Shift the value to the right 00294 value >>= 7; 00295 00296 //Encode the remaining bytes 00297 for(n = 1; value != 0; n++) 00298 { 00299 //Encode current byte 00300 temp[n] = OID_MORE_FLAG | (value & OID_VALUE_MASK); 00301 //Shift the value to the right 00302 value >>= 7; 00303 } 00304 } 00305 00306 //Sanity check 00307 if(n > maxOidLen) 00308 { 00309 //Report an error 00310 error = ERROR_BUFFER_OVERFLOW; 00311 break; 00312 } 00313 00314 //Write the current sub-identifier 00315 for(j = 0; j < n; j++) 00316 oid[j] = temp[n - j - 1]; 00317 00318 //Advance write pointer 00319 oid += n; 00320 *oidLen += n; 00321 maxOidLen -= n; 00322 00323 //Number of sub-identifiers 00324 i++; 00325 00326 //End of string detected? 00327 if(*str == '\0') 00328 { 00329 //The conversion succeeded 00330 error = NO_ERROR; 00331 break; 00332 } 00333 } 00334 //Invalid character... 00335 else 00336 { 00337 //The conversion failed 00338 error = ERROR_INVALID_SYNTAX; 00339 break; 00340 } 00341 00342 //Point to the next character 00343 str++; 00344 } 00345 00346 //Return status code 00347 return error; 00348 } 00349 00350 00351 /** 00352 * @brief Convert a binary OID to a string representation 00353 * @param[in] oid Object identifier 00354 * @param[in] oidLen Length of the object identifier, in bytes 00355 * @param[out] str NULL-terminated string representing the OID 00356 * @param[in] maxStrLen Maximum length of the resulting string 00357 * @return Pointer to the formatted string 00358 **/ 00359 00360 char_t *oidToString(const uint8_t *oid, 00361 size_t oidLen, char_t *str, size_t maxStrLen) 00362 { 00363 static char_t buffer[64]; 00364 size_t i; 00365 size_t n; 00366 uint32_t value; 00367 char_t *p; 00368 char_t temp[12]; 00369 00370 //The str parameter is optional 00371 if(str == NULL) 00372 { 00373 //Point to the internal buffer 00374 str = buffer; 00375 //Maximum length of the resulting string 00376 maxStrLen = sizeof(buffer) - 1; 00377 } 00378 00379 //Point the beginning of the string 00380 p = str; 00381 //Properly terminate the string 00382 *p = '\0'; 00383 00384 //Check the length of the OID 00385 if(oidLen > 0) 00386 { 00387 //Convert the first 2 bytes 00388 n = sprintf(temp, "%" PRIu8 ".%" PRIu8 "", oid[0] / 40, oid[0] % 40); 00389 00390 //Sanity check 00391 if(n <= maxStrLen) 00392 { 00393 //Copy the resulting string 00394 strcpy(p, temp); 00395 //Advance write pointer 00396 p += n; 00397 maxStrLen -= n; 00398 } 00399 00400 //Initialize the value of the sub-identifier 00401 value = 0; 00402 00403 //Convert the rest of the OID 00404 for(i = 1; i < oidLen; i++) 00405 { 00406 //Shift the value to the left 00407 value <<= 7; 00408 //Update the current value 00409 value |= oid[i] & OID_VALUE_MASK; 00410 00411 //Bit b8 is set to zero to indicate the last byte 00412 if(!(oid[i] & OID_MORE_FLAG)) 00413 { 00414 //Dump current value 00415 n = sprintf(temp, ".%" PRIu32, value); 00416 00417 //Sanity check 00418 if(n <= maxStrLen) 00419 { 00420 //Copy the resulting string 00421 strcpy(p, temp); 00422 //Advance write pointer 00423 p += n; 00424 maxStrLen -= n; 00425 } 00426 00427 //Prepare to decode the next value 00428 value = 0; 00429 } 00430 } 00431 } 00432 00433 //Return a pointer to the formatted string 00434 return str; 00435 } 00436 00437 #endif 00438
Generated on Tue Jul 12 2022 17:10:15 by
