oid.c
Go to the documentation of this file.
1 /**
2  * @file oid.c
3  * @brief OID (Object Identifier)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2019 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCrypto Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 1.9.6
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/crypto.h"
36 #include "encoding/oid.h"
37 #include "debug.h"
38 
39 //Check crypto library configuration
40 #if (OID_SUPPORT == ENABLED)
41 
42 
43 /**
44  * @brief Check whether the specified object identifier is valid
45  * @param[in] oid Pointer to the object identifier
46  * @param[in] oidLen Length of the OID, in bytes
47  * @return Error code
48  **/
49 
50 error_t oidCheck(const uint8_t *oid, size_t oidLen)
51 {
52  size_t i;
53  size_t n;
54 
55  //Check parameters
56  if(oid == NULL)
58 
59  //Check the length of the OID
60  if(oidLen == 0)
61  {
62  //Report an error
63  return ERROR_INVALID_SYNTAX;
64  }
65  else if(oidLen > 1)
66  {
67  //Parse the object identifier
68  for(i = 1, n = 2; i < oidLen; i++)
69  {
70  //Update the total number of nodes
71  if(!(oid[i] & OID_MORE_FLAG))
72  n++;
73 
74  //SNMP limits object identifier values to a maximum of 128 nodes
75  if(n > 128)
76  return ERROR_INVALID_SYNTAX;
77  }
78 
79  //Ensure that the last sub-identifier is valid
80  if(oid[oidLen - 1] & OID_MORE_FLAG)
81  return ERROR_INVALID_SYNTAX;
82  }
83 
84  //The specified OID is valid
85  return NO_ERROR;
86 }
87 
88 
89 /**
90  * @brief Compare object identifiers
91  * @param[in] oid1 Pointer the first OID
92  * @param[in] oidLen1 Length of the first OID, in bytes
93  * @param[in] oid2 Pointer the second OID
94  * @param[in] oidLen2 Length of the second OID, in bytes
95  * @return Comparison result
96  * @retval 0 Objects identifiers are equal
97  * @retval -1 The first OID lexicographically precedes the second OID
98  * @retval 1 The second OID lexicographically precedes the first OID
99  **/
100 
101 int_t oidComp(const uint8_t *oid1, size_t oidLen1, const uint8_t *oid2,
102  size_t oidLen2)
103 {
104  size_t i;
105 
106  //Perform lexicographical comparison
107  for(i = 0; i < oidLen1 && i < oidLen2; i++)
108  {
109  //Compare current byte
110  if(oid1[i] < oid2[i])
111  return -1;
112  else if(oid1[i] > oid2[i])
113  return 1;
114  }
115 
116  //Compare length
117  if(oidLen1 < oidLen2)
118  return -1;
119  else if(oidLen1 > oidLen2)
120  return 1;
121 
122  //Object identifiers are equal
123  return 0;
124 }
125 
126 
127 /**
128  * @brief Check whether an OID matches the specified subtree
129  * @param[in] oid Pointer to the object identifier
130  * @param[in] oidLen Length of the OID, in bytes
131  * @param[in] subtree Pointer to the subtree
132  * @param[in] subtreeLen Length of the subtree, in bytes
133  * @param[in] mask Pointer to the mask
134  * @param[in] maskLen Length of the mask, in bytes
135  * @return TRUE if the OID matches the specified subtree, else FALSE
136  **/
137 
138 bool_t oidMatch(const uint8_t *oid, size_t oidLen, const uint8_t *subtree,
139  size_t subtreeLen, const uint8_t *mask, size_t maskLen)
140 {
141  size_t i;
142  uint8_t flag;
143  size_t oidPos;
144  size_t subtreePos;
145 
146  //Initialize variables
147  oidPos = 0;
148  subtreePos = 0;
149 
150  //Check whether the OID matches the specified subtree
151  for(i = 0; subtreePos < subtreeLen; i++)
152  {
153  //Check the length of the OID
154  if(oidPos >= oidLen)
155  return FALSE;
156 
157  //The bit mask is extended with 1's to be the required length
158  if((i / 8) < maskLen)
159  flag = mask[i / 8] & (1 << (7 - (i % 8)));
160  else
161  flag = 1;
162 
163  //First node?
164  if(i == 0)
165  {
166  //The mask allows for a simple form of wildcarding
167  if(flag)
168  {
169  //Compare the first sub-identifier
170  if((oid[0] / 40) != (subtree[0] / 40))
171  return FALSE;
172  }
173  }
174  //Second node?
175  else if(i == 1)
176  {
177  //The mask allows for a simple form of wildcarding
178  if(flag)
179  {
180  //Compare the second sub-identifier
181  if((oid[0] % 40) != (subtree[0] % 40))
182  return FALSE;
183  }
184 
185  //Jump to the next node
186  oidPos = 1;
187  subtreePos = 1;
188  }
189  //Remaining nodes?
190  else
191  {
192  //The mask allows for a simple form of wildcarding
193  if(flag)
194  {
195  //Compare sub-identifiers
196  while(1)
197  {
198  //Compare the current byte
199  if(oid[oidPos] != subtree[subtreePos])
200  return FALSE;
201 
202  //Bit b8 is set to zero to indicate the last byte
203  flag = oid[oidPos] & OID_MORE_FLAG;
204 
205  //Next byte
206  oidPos++;
207  subtreePos++;
208 
209  //Last byte of the sub-identifier?
210  if(!flag)
211  break;
212 
213  //Check the length of the OID
214  if(oidPos >= oidLen)
215  return FALSE;
216 
217  //Check the length of the subtree
218  if(subtreePos > subtreeLen)
219  return FALSE;
220  }
221  }
222  else
223  {
224  //Read the OID until the last byte of the sub-identifier is found
225  while(1)
226  {
227  //Bit b8 is set to zero to indicate the last byte
228  flag = oid[oidPos] & OID_MORE_FLAG;
229 
230  //Next byte
231  oidPos++;
232 
233  //Last byte of the sub-identifier?
234  if(!flag)
235  break;
236 
237  //Check the length of the OID
238  if(oidPos >= oidLen)
239  return FALSE;
240  }
241 
242  //Read the subtree until the last byte of the sub-identifier is found
243  while(1)
244  {
245  //Bit b8 is set to zero to indicate the last byte
246  flag = subtree[subtreePos] & OID_MORE_FLAG;
247 
248  //Next byte
249  subtreePos++;
250 
251  //Last byte of the sub-identifier?
252  if(!flag)
253  break;
254 
255  //Check the length of the subtree
256  if(subtreePos >= subtreeLen)
257  return FALSE;
258  }
259  }
260  }
261  }
262 
263  //The OID matches the specified subtree
264  return TRUE;
265 }
266 
267 
268 /**
269  * @brief Calculate the number of sub-identifiers
270  * @param[in] oid Pointer to the object identifier
271  * @param[in] oidLen Length of the OID, in bytes
272  * @return Number of sub-identifiers
273  **/
274 
275 uint_t oidCountSubIdentifiers(const uint8_t *oid, size_t oidLen)
276 {
277  size_t i;
278  uint_t n;
279 
280  //Check the length of the OID
281  if(oidLen == 0)
282  {
283  //The OID is empty
284  n = 0;
285  }
286  else
287  {
288  //The first byte encodes two sub-identifiers
289  n = 2;
290 
291  //Parse the object identifier
292  for(i = 1; i < oidLen; i++)
293  {
294  //Update the total number of sub-identifiers
295  if(!(oid[i] & OID_MORE_FLAG))
296  n++;
297  }
298  }
299 
300  //Return the total number of sub-identifiers
301  return n;
302 }
303 
304 
305 /**
306  * @brief Encode OID sub-identifier
307  * @param[in] oid Pointer to the object identifier
308  * @param[in] maxOidLen Maximum number of bytes the OID can hold
309  * @param[in,out] pos Offset where to write the sub-identifier
310  * @param[in] value Value of the sub-identifier
311  * @return Error code
312  **/
313 
314 error_t oidEncodeSubIdentifier(uint8_t *oid, size_t maxOidLen,
315  size_t *pos, uint32_t value)
316 {
317  size_t i;
318  size_t n;
319  uint8_t temp[5];
320 
321  //Encode the first byte of the sub-identifier
322  temp[0] = value & OID_VALUE_MASK;
323  //Shift the value to the right
324  value >>= 7;
325 
326  //Encode the remaining bytes
327  for(n = 1; value != 0; n++)
328  {
329  //Encode current byte
330  temp[n] = OID_MORE_FLAG | (value & OID_VALUE_MASK);
331  //Shift the value to the right
332  value >>= 7;
333  }
334 
335  //Sanity check
336  if((*pos + n) > maxOidLen)
337  return ERROR_BUFFER_OVERFLOW;
338 
339  //Write the current sub-identifier
340  for(i = 0; i < n; i++)
341  {
342  oid[*pos + i] = temp[n - i - 1];
343  }
344 
345  //Update offset value
346  *pos += n;
347 
348  //Successful processing
349  return NO_ERROR;
350 }
351 
352 
353 /**
354  * @brief Decode OID sub-identifier
355  * @param[in] oid Pointer to the object identifier
356  * @param[in] oidLen Length of the OID, in bytes
357  * @param[in,out] pos Offset where to read the sub-identifier
358  * @param[out] value Value of the sub-identifier
359  * @return Error code
360  **/
361 
362 error_t oidDecodeSubIdentifier(const uint8_t *oid, size_t oidLen,
363  size_t *pos, uint32_t *value)
364 {
365  size_t i;
366 
367  //Initialize the value of the sub-identifier
368  *value = 0;
369 
370  //Read the OID until the last byte of the sub-identifier is found
371  for(i = *pos; i < oidLen; i++)
372  {
373  //Shift the value to the left
374  *value <<= 7;
375  //Update value of the sub-identifier
376  *value |= oid[i] & OID_VALUE_MASK;
377 
378  //Bit b8 is set to zero to indicate the last byte
379  if(!(oid[i] & OID_MORE_FLAG))
380  {
381  //Update offset value
382  *pos = i + 1;
383  //Successful processing
384  return NO_ERROR;
385  }
386  }
387 
388  //The specified OID is not valid
389  return ERROR_INVALID_SYNTAX;
390 }
391 
392 
393 /**
394  * @brief Convert a string representation of an OID to a binary OID
395  * @param[in] str NULL-terminated string representing the OID
396  * @param[out] oid Object identifier
397  * @param[in] maxOidLen Maximum number of bytes the OID can hold
398  * @param[out] oidLen Length of the object identifier
399  * @return Error code
400  **/
401 
402 error_t oidFromString(const char_t *str, uint8_t *oid, size_t maxOidLen,
403  size_t *oidLen)
404 {
405  error_t error;
406  size_t i;
407  size_t j;
408  size_t n;
409  uint32_t value;
410  uint8_t temp[5];
411 
412  //Reset the length of the OID
413  *oidLen = 0;
414 
415  //Number of nodes
416  i = 0;
417  //Initialize the value of the sub-identifier
418  value = 0;
419 
420  //Parse input string
421  while(1)
422  {
423  //Digit found?
424  if(cryptoIsdigit(*str))
425  {
426  //Update the value of the sub-identifier
427  value = (value * 10) + (*str - '0');
428  }
429  //Separator or end of string found?
430  else if(*str == '.' || *str == '\0')
431  {
432  //First node?
433  if(i == 0)
434  {
435  //Check value
436  if(value > 6)
437  {
438  //The conversion failed
439  error = ERROR_INVALID_SYNTAX;
440  break;
441  }
442 
443  //Encode the first sub-identifier
444  temp[0] = value * 40;
445  //Prepare to decode the next node
446  value = 0;
447  //Do not write current sub-identifier yet
448  n = 0;
449  }
450  //Second node?
451  else if(i == 1)
452  {
453  //Check value
454  if(value > 39)
455  {
456  //The conversion failed
457  error = ERROR_INVALID_SYNTAX;
458  break;
459  }
460 
461  //Encode the second sub-identifier
462  temp[0] += value;
463  //Prepare to decode the next node
464  value = 0;
465  //Write the first two sub-identifiers
466  n = 1;
467  }
468  //Remaining nodes?
469  else
470  {
471  //Encode the first byte of the sub-identifier
472  temp[0] = value & OID_VALUE_MASK;
473  //Shift the value to the right
474  value >>= 7;
475 
476  //Encode the remaining bytes
477  for(n = 1; value != 0; n++)
478  {
479  //Encode current byte
480  temp[n] = OID_MORE_FLAG | (value & OID_VALUE_MASK);
481  //Shift the value to the right
482  value >>= 7;
483  }
484  }
485 
486  //Sanity check
487  if(n > maxOidLen)
488  {
489  //Report an error
490  error = ERROR_BUFFER_OVERFLOW;
491  break;
492  }
493 
494  //Write the current sub-identifier
495  for(j = 0; j < n; j++)
496  {
497  oid[j] = temp[n - j - 1];
498  }
499 
500  //Advance write pointer
501  oid += n;
502  *oidLen += n;
503  maxOidLen -= n;
504 
505  //Number of sub-identifiers
506  i++;
507 
508  //End of string detected?
509  if(*str == '\0')
510  {
511  //The conversion succeeded
512  error = NO_ERROR;
513  break;
514  }
515  }
516  //Invalid character...
517  else
518  {
519  //The conversion failed
520  error = ERROR_INVALID_SYNTAX;
521  break;
522  }
523 
524  //Point to the next character
525  str++;
526  }
527 
528  //Return status code
529  return error;
530 }
531 
532 
533 /**
534  * @brief Convert a binary OID to a string representation
535  * @param[in] oid Object identifier
536  * @param[in] oidLen Length of the object identifier, in bytes
537  * @param[out] str NULL-terminated string representing the OID
538  * @param[in] maxStrLen Maximum length of the resulting string
539  * @return Pointer to the formatted string
540  **/
541 
542 char_t *oidToString(const uint8_t *oid, size_t oidLen, char_t *str,
543  size_t maxStrLen)
544 {
545  static char_t buffer[128];
546  size_t i;
547  size_t n;
548  uint32_t value;
549  char_t *p;
550  char_t temp[12];
551 
552  //The str parameter is optional
553  if(str == NULL)
554  {
555  //Point to the internal buffer
556  str = buffer;
557  //Maximum length of the resulting string
558  maxStrLen = sizeof(buffer) - 1;
559  }
560 
561  //Point to the beginning of the string
562  p = str;
563  //Properly terminate the string
564  *p = '\0';
565 
566  //Check the length of the OID
567  if(oidLen > 0)
568  {
569  //Convert the first 2 bytes
570  n = sprintf(temp, "%" PRIu8 ".%" PRIu8 "", oid[0] / 40, oid[0] % 40);
571 
572  //Sanity check
573  if(n <= maxStrLen)
574  {
575  //Copy the resulting string
576  cryptoStrcpy(p, temp);
577  //Advance write pointer
578  p += n;
579  maxStrLen -= n;
580  }
581 
582  //Initialize the value of the sub-identifier
583  value = 0;
584 
585  //Convert the rest of the OID
586  for(i = 1; i < oidLen; i++)
587  {
588  //Shift the value to the left
589  value <<= 7;
590  //Update the current value
591  value |= oid[i] & OID_VALUE_MASK;
592 
593  //Bit b8 is set to zero to indicate the last byte
594  if(!(oid[i] & OID_MORE_FLAG))
595  {
596  //Dump current value
597  n = sprintf(temp, ".%" PRIu32, value);
598 
599  //Sanity check
600  if(n <= maxStrLen)
601  {
602  //Copy the resulting string
603  cryptoStrcpy(p, temp);
604  //Advance write pointer
605  p += n;
606  maxStrLen -= n;
607  }
608 
609  //Prepare to decode the next value
610  value = 0;
611  }
612  }
613  }
614 
615  //Return a pointer to the formatted string
616  return str;
617 }
618 
619 
620 /**
621  * @brief Convert a bit mask to binary representation
622  * @param[in] str NULL-terminated string representing the bit mask
623  * @param[out] mask Pointer to the buffer where to store the resulting mask
624  * @param[in] maxMaskLen Maximum number of bytes the buffer can hold
625  * @param[out] maskLen Length of the mask
626  * @return Error code
627  **/
628 
629 error_t maskFromString(const char_t *str, uint8_t *mask, size_t maxMaskLen,
630  size_t *maskLen)
631 {
632  error_t error;
633  size_t i;
634  size_t j;
635 
636  //Point to the first byte
637  i = 0;
638  //Point to the most-significant bit
639  j = 8;
640 
641  //Parse input string
642  while(1)
643  {
644  //Check current character
645  if(*str == '0' || *str == '1')
646  {
647  //Make sure the output buffer is large enough
648  if(i >= maxMaskLen)
649  {
650  //Report an error
651  error = ERROR_BUFFER_OVERFLOW;
652  break;
653  }
654 
655  //Update bit mask
656  if(*str == '1')
657  mask[i] |= (1 << (j - 1));
658  else
659  mask[i] &= ~(1 << (j - 1));
660 
661  //Next bit
662  j--;
663  }
664  else if(*str == '\0')
665  {
666  //End of string detected
667  error = NO_ERROR;
668  break;
669  }
670  else
671  {
672  //Discard any other characters
673  }
674 
675  //Check whether the least-significant bit has been reached
676  if(j == 0)
677  {
678  //Point to the most-significant bit of the next byte
679  j = 8;
680  i++;
681  }
682 
683  //Point to the next character
684  str++;
685  }
686 
687  //Check status code
688  if(!error)
689  {
690  //Incomplete byte?
691  if(j < 8)
692  {
693  //The bit mask is extended with 1's to be the required length
694  mask[i] |= (1 << j) - 1;
695  //Save the length of the resulting mask
696  *maskLen = i + 1;
697  }
698  else
699  {
700  //Save the length of the resulting mask
701  *maskLen = i;
702  }
703  }
704 
705  //Return status code
706  return error;
707 }
708 
709 #endif
int bool_t
Definition: compiler_port.h:49
signed int int_t
Definition: compiler_port.h:44
error_t maskFromString(const char_t *str, uint8_t *mask, size_t maxMaskLen, size_t *maskLen)
Convert a bit mask to binary representation.
Definition: oid.c:629
error_t oidFromString(const char_t *str, uint8_t *oid, size_t maxOidLen, size_t *oidLen)
Convert a string representation of an OID to a binary OID.
Definition: oid.c:402
OID (Object Identifier)
uint8_t p
Definition: ndp.h:298
#define TRUE
Definition: os_port.h:50
error_t oidEncodeSubIdentifier(uint8_t *oid, size_t maxOidLen, size_t *pos, uint32_t value)
Encode OID sub-identifier.
Definition: oid.c:314
int_t oidComp(const uint8_t *oid1, size_t oidLen1, const uint8_t *oid2, size_t oidLen2)
Compare object identifiers.
Definition: oid.c:101
error_t oidDecodeSubIdentifier(const uint8_t *oid, size_t oidLen, size_t *pos, uint32_t *value)
Decode OID sub-identifier.
Definition: oid.c:362
#define FALSE
Definition: os_port.h:46
Invalid parameter.
Definition: error.h:47
#define OID_MORE_FLAG
Definition: oid.h:38
error_t
Error codes.
Definition: error.h:42
bool_t oidMatch(const uint8_t *oid, size_t oidLen, const uint8_t *subtree, size_t subtreeLen, const uint8_t *mask, size_t maskLen)
Check whether an OID matches the specified subtree.
Definition: oid.c:138
General definitions for cryptographic algorithms.
uint8_t oid[1]
Definition: mib_common.h:186
uint8_t mask
Definition: web_socket.h:317
char char_t
Definition: compiler_port.h:43
error_t oidCheck(const uint8_t *oid, size_t oidLen)
Check whether the specified object identifier is valid.
Definition: oid.c:50
uint_t oidCountSubIdentifiers(const uint8_t *oid, size_t oidLen)
Calculate the number of sub-identifiers.
Definition: oid.c:275
uint8_t n
char_t * oidToString(const uint8_t *oid, size_t oidLen, char_t *str, size_t maxStrLen)
Convert a binary OID to a string representation.
Definition: oid.c:542
#define OID_VALUE_MASK
Definition: oid.h:39
uint8_t value[]
Definition: dtls_misc.h:150
#define cryptoStrcpy(s1, s2)
Definition: crypto.h:666
unsigned int uint_t
Definition: compiler_port.h:45
#define cryptoIsdigit(c)
Definition: crypto.h:696
Success.
Definition: error.h:44
Debugging facilities.