openssl源码解读——i2d和d2i系列函数
来源:互联网 发布:expect for windows 编辑:程序博客网 时间:2024/06/09 14:14
i2d和d2i系列函数
首先查看man文档(比如 man i2d_x509),可知:
SYNOPSIS
TYPE *d2i_TYPE(TYPE **a, unsigned char **pp, long length);TYPE *d2i_TYPE_bio(BIO *bp, TYPE **a);TYPE *d2i_TYPE_fp(FILE *bp, TYPE **a);int i2d_TYPE(TYPE **a, unsigned char **pp);int i2d_TYPE_bio(BIO *bp, TYPE **a);int i2d_TYPE_fp(FILE *bp, TYPE **a);
TYPE is used a placeholder for any of the OpenSSL datatypes, such as X509_CRL.
These functions convert OpenSSL objects to and from their ASN.1/DER encoding. Unlike the C structures which can have pointers to sub-objects within, the DER is a serialized encoding, suitable for sending over the network, writing to a file, and so on.
d2i_TYPE() attempts to decode len bytes at *in.If successful a pointer to the TYPE structure is returned and *in is incremented to the byte following the parsed data. If a is not NULL then a pointer to the returned structure is also written to *a. If an error occurred then NULL is returned.
On a successful return, if *a is not NULL then it is assumed that *a contains a valid TYPE structure and an attempt is made to reuse it. This "reuse" capability is present for historical compatibility but its use is strongly discouraged (see BUGS below,and the discussion in the RETURN VALUES section).
d2i_TYPE_bio() is similar to d2i_TYPE() except it attempts to parse data from BIO bp.
d2i_TYPE_fp() is similar to d2i_TYPE() except it attempts to parse data from FILE pointer fp.
d2i_TYPE_fp() is similar to d2i_TYPE() except it attempts to parse data from FILE pointer fp.
i2d_TYPE() encodes the structure pointed to by a into DER format. If out is not NULL, it writes the DER encoded data to the buffer at *out, and increments it to point after the data just written. If the return value is negative an error occurred, otherwise it returns the length of the encoded data.
If *out is NULL memory will be allocated for a buffer and the encoded data written to it. In this case *out is not incremented and it points to the start of the data just written.
i2d_TYPE_bio() is similar to i2d_TYPE() except it writes the encoding of the structure a to BIO bp and it returns 1 for success and 0 for failure.
i2d_TYPE_fp() is similar to i2d_TYPE() except it writes the encoding of the structure a to BIO bp and it returns 1 for success and 0 for failure.
These routines do not encrypt private keys and therefore offer no security; use PEM_write_PrivateKey(3) or similar for writing to files.
If *out is NULL memory will be allocated for a buffer and the encoded data written to it. In this case *out is not incremented and it points to the start of the data just written.
i2d_TYPE_bio() is similar to i2d_TYPE() except it writes the encoding of the structure a to BIO bp and it returns 1 for success and 0 for failure.
i2d_TYPE_fp() is similar to i2d_TYPE() except it writes the encoding of the structure a to BIO bp and it returns 1 for success and 0 for failure.
These routines do not encrypt private keys and therefore offer no security; use PEM_write_PrivateKey(3) or similar for writing to files.
NOTES
The letters i and d in i2d_TYPE stand for"internal" (that is, an internal C structure) and"DER" respectively. So i2d_TYPE converts from internal to DER.
The following points about the data types might be useful:
ASN1_OBJECT
Represents an ASN1 OBJECT IDENTIFIER.
DHparams
Represents a PKCS#3 DH parameters structure.
DHparamx
Represents a ANSI X9.42 DH parameters structure.
DSA_PUBKEY
Represents a DSA public key using a SubjectPublicKeyInfo structure.
DSAPublicKey, DSAPrivateKey
Use a non-standard OpenSSL format and should be avoided; use DSA_PUBKEY, PEM_write_PrivateKey(3), or similar instead.
RSAPublicKey
Represents a PKCS#1 RSA public key structure.
X509_ALGOR
Represents an AlogrithmIdentifier structure as used in IETF RFC 6960 and elsewhere.
X509_Name
Represents a Name type as used for subject and issuer names in IETF RFC 6960 and elsewhere.
X509_REQ
Represents a PKCS#10 certificate request.
X509_SIG
Represents the DigestInfo structure defined in PKCS#1 and PKCS#7.
ASN1_OBJECT
Represents an ASN1 OBJECT IDENTIFIER.
DHparams
Represents a PKCS#3 DH parameters structure.
DHparamx
Represents a ANSI X9.42 DH parameters structure.
DSA_PUBKEY
Represents a DSA public key using a SubjectPublicKeyInfo structure.
DSAPublicKey, DSAPrivateKey
Use a non-standard OpenSSL format and should be avoided; use DSA_PUBKEY, PEM_write_PrivateKey(3), or similar instead.
RSAPublicKey
Represents a PKCS#1 RSA public key structure.
X509_ALGOR
Represents an AlogrithmIdentifier structure as used in IETF RFC 6960 and elsewhere.
X509_Name
Represents a Name type as used for subject and issuer names in IETF RFC 6960 and elsewhere.
X509_REQ
Represents a PKCS#10 certificate request.
X509_SIG
Represents the DigestInfo structure defined in PKCS#1 and PKCS#7.
——————————————————————————————————————————————————————————————————————
下面查看openssl源码:
在asn1.h文件中发现如下一系列宏定义,
/* Declare ASN1 functions: the implement macro in in asn1t.h */# define DECLARE_ASN1_FUNCTIONS(type) DECLARE_ASN1_FUNCTIONS_name(type, type)# define DECLARE_ASN1_ALLOC_FUNCTIONS(type) \ DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, type)# define DECLARE_ASN1_FUNCTIONS_name(type, name) \ DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name)# define DECLARE_ASN1_FUNCTIONS_fname(type, itname, name) \ DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name)# define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) \ type *d2i_##name(type **a, const unsigned char **in, long len); \ int i2d_##name(type *a, unsigned char **out); \ DECLARE_ASN1_ITEM(itname)# define DECLARE_ASN1_ENCODE_FUNCTIONS_const(type, name) \ type *d2i_##name(type **a, const unsigned char **in, long len); \ int i2d_##name(const type *a, unsigned char **out); \ DECLARE_ASN1_ITEM(name)# define DECLARE_ASN1_FUNCTIONS_const(name) \ DECLARE_ASN1_ALLOC_FUNCTIONS(name) \ DECLARE_ASN1_ENCODE_FUNCTIONS_const(name, name)# define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ type *name##_new(void); \ void name##_free(type *a);
/* * Platforms that can't easily handle shared global variables are declared as * functions returning ASN1_ITEM pointers. *//* ASN1_ITEM pointer exported type */typedef const ASN1_ITEM *ASN1_ITEM_EXP (void);/* Macro to obtain ASN1_ITEM pointer from exported type */# define ASN1_ITEM_ptr(iptr) (iptr())/* Macro to include ASN1_ITEM pointer from base type */# define ASN1_ITEM_ref(iptr) (iptr##_it)# define ASN1_ITEM_rptr(ref) (ref##_it())# define DECLARE_ASN1_ITEM(name) \ const ASN1_ITEM * name##_it(void);
DECLARE_ASN1_FUNCTIONS(ASN1_BIT_STRING)DECLARE_ASN1_FUNCTIONS(ASN1_INTEGER)...DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo)DECLARE_ASN1_FUNCTIONS(CMS_ReceiptRequest)...DECLARE_ASN1_FUNCTIONS(PKCS12)DECLARE_ASN1_FUNCTIONS(PKCS12_MAC_DATA)...DECLARE_ASN1_FUNCTIONS(PKCS7_ENCRYPT)DECLARE_ASN1_FUNCTIONS(PKCS7)...DECLARE_ASN1_FUNCTIONS(X509_NAME)DECLARE_ASN1_FUNCTIONS(X509_CINF)DECLARE_ASN1_FUNCTIONS(X509)...
对于DECLARE_ASN1_FUNCTIONS(X509),经过宏扩展后,变成如下:
X509 *d2i_X509(X509 **a, const unsigned char **in, long len);int i2d_X509(X509 *a, unsigned char **out);const ASN1_ITEM * X509_it(void);X509 *X509_new(void); \void X509_free(X509 *a);
/* Macro to implement standard functions in terms of ASN1_ITEM structures */# define IMPLEMENT_ASN1_FUNCTIONS(stname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, stname, stname)# define IMPLEMENT_ASN1_FUNCTIONS_name(stname, itname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, itname)# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS(stname) \ IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, stname, stname)}# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) \ stname *fname##_new(void) \ { \ return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \ } \ void fname##_free(stname *a) \ { \ ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \ }# define IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, fname) \ IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname)# define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ stname *d2i_##fname(stname **a, const unsigned char **in, long len) \ { \ return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\ } \ int i2d_##fname(stname *a, unsigned char **out) \ { \ return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ }
然后在tasn_typ.c、p12_asn1.c、pk7_asn1.c、x_x509.c中发现很多关于IMPLEMENT_ASN1_FUNCTIONS的调用,例如:
IMPLEMENT_ASN1_FUNCTIONS(ASN1_INTEGER)IMPLEMENT_ASN1_FUNCTIONS(ASN1_ENUMERATED)...IMPLEMENT_ASN1_FUNCTIONS(PKCS12)IMPLEMENT_ASN1_FUNCTIONS(PKCS12_MAC_DATA)...IMPLEMENT_ASN1_FUNCTIONS(PKCS7)IMPLEMENT_ASN1_FUNCTIONS(PKCS7_SIGNED)...IMPLEMENT_ASN1_FUNCTIONS(X509_CINF)IMPLEMENT_ASN1_FUNCTIONS(X509)...
对于IMPLEMENT_ASN1_FUNCTIONS(X509),经过宏扩展后,变成如下:
X509 *X509_new(void){ return (X509 *)ASN1_item_new(X509_it);}void X509_free(X509 *a){ ASN1_item_free((ASN1_VALUE *)a, X509_it);}X509 *d2i_X509(X509 **a, const unsigned char **in, long len){ return (X509 *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, X509_it);}int i2d_X509(X509 *a, unsigned char **out){ return ASN1_item_i2d((ASN1_VALUE *)a, out, X509_it);}
经过上面的分析,我们已经很清楚了i2d和d2i系列的函数的定义和实现过程。但对const ASN1_ITEM * name##_it(void)的实现还清楚。下面说其实现过程:
首先,我们在asn1t.h中找到:
/* Macros for start and end of ASN1_ITEM definition */# define ASN1_ITEM_start(itname) \ const ASN1_ITEM * itname##_it(void) \ { \ static const ASN1_ITEM local_it = {# define ASN1_ITEM_end(itname) \ }; \ return &local_it; \ }然后去寻找local_it。再asn1t.h中找到,
# define ASN1_SEQUENCE_END_ref(stname, tname) \ ;\ ASN1_ITEM_start(tname) \ ASN1_ITYPE_SEQUENCE,\ V_ASN1_SEQUENCE,\ tname##_seq_tt,\ sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ &tname##_aux,\ sizeof(stname),\ #stname \ ASN1_ITEM_end(tname)然后在x_x509.c中发现了ASN1_SEQUENCE_END_ref的使用,
ASN1_SEQUENCE_ref(X509, x509_cb, CRYPTO_LOCK_X509) = { ASN1_SIMPLE(X509, cert_info, X509_CINF), ASN1_SIMPLE(X509, sig_alg, X509_ALGOR), ASN1_SIMPLE(X509, signature, ASN1_BIT_STRING)} ASN1_SEQUENCE_END_ref(X509, X509)
查看ASN1_ITEM结构体定义:
/* This is the actual ASN1 item itself */struct ASN1_ITEM_st { char itype; /* The item type, primitive, SEQUENCE, CHOICE * or extern */ long utype; /* underlying type */ const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains * the contents */ long tcount; /* Number of templates if SEQUENCE or CHOICE */ const void *funcs; /* functions that handle this type */ long size; /* Structure size (usually) */# ifndef NO_ASN1_FIELD_NAMES const char *sname; /* Structure name */# endif};
所以:
const ASN1_ITEM *X509_it(void){ static const ASN1_ITEM local_it = { ASN1_ITYPE_SEQUENCE, V_ASN1_SEQUENCE, X509_seq_tt, sizeof(X509_seq_tt) / sizeof(ASN1_TEMPLATE), &X509_aux, sizeof(X509), "X509" }; return &local_it;}
1 0
- openssl源码解读——i2d和d2i系列函数
- openssl 代码分析(2)----i2d和d2i系列函数
- Openssl ASN.1 说明二(i2d d2i) 分享
- Tomcat源码解读系列(二)——Tomcat的核心组成和启动过程
- Tomcat源码解读系列——Tomcat的核心组成和启动过程
- Tomcat源码解读系列(二)——Tomcat的核心组成和启动过程
- openlayers4源码解读系列
- openssl中ASN.1源码解读
- SSD的源码解读——MultiBoxLoss函数定义
- Alamofire源码解读系列(一)之概述和使用
- PhotoSwipe源码解读系列(二)
- java集合源码解读系列
- Spark之 源码解读系列
- leaflet1.2.0源码解读系列
- OpenSSL之EVP(二)——EVP系列函数介绍
- OpenCV的GrabCut函数使用和源码解读
- OpenCV的GrabCut函数使用和源码解读
- opencv之GrabCut函数使用和源码解读
- bzoj 2597: [Wc2007]剪刀石头布(费用流)
- 面试题27:二叉搜索树与双向链表
- qemu中的Hbitmap数据结构
- 大家乐捕鱼游戏里的onOpen函数
- 软件测试 (二) 如何测试网页的登录页面
- openssl源码解读——i2d和d2i系列函数
- 异常控制流
- 如何防御SQL注入
- React复合组件
- oc常用函数
- 使用Unity开发GearVR应用
- 数据库常用语句汇总
- Sublime Text 3常用快捷键
- Android 内存与性能