Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers oid.c Source File

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