diff options
Diffstat (limited to 'src/lib/libcrypto/pem/pem_lib.c')
-rw-r--r-- | src/lib/libcrypto/pem/pem_lib.c | 222 |
1 files changed, 191 insertions, 31 deletions
diff --git a/src/lib/libcrypto/pem/pem_lib.c b/src/lib/libcrypto/pem/pem_lib.c index 90f02011ba..072211ba0f 100644 --- a/src/lib/libcrypto/pem/pem_lib.c +++ b/src/lib/libcrypto/pem/pem_lib.c | |||
@@ -75,8 +75,17 @@ const char *PEM_version="PEM" OPENSSL_VERSION_PTEXT; | |||
75 | 75 | ||
76 | static int def_callback(char *buf, int num, int w, void *userdata); | 76 | static int def_callback(char *buf, int num, int w, void *userdata); |
77 | static int load_iv(unsigned char **fromp,unsigned char *to, int num); | 77 | static int load_iv(unsigned char **fromp,unsigned char *to, int num); |
78 | 78 | static int check_pem(const char *nm, const char *name); | |
79 | static int def_callback(char *buf, int num, int w, void *userdata) | 79 | static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, |
80 | int nid, const EVP_CIPHER *enc, | ||
81 | char *kstr, int klen, | ||
82 | pem_password_cb *cb, void *u); | ||
83 | static int do_pk8pkey_fp(FILE *bp, EVP_PKEY *x, int isder, | ||
84 | int nid, const EVP_CIPHER *enc, | ||
85 | char *kstr, int klen, | ||
86 | pem_password_cb *cb, void *u); | ||
87 | |||
88 | static int def_callback(char *buf, int num, int w, void *key) | ||
80 | { | 89 | { |
81 | #ifdef NO_FP_API | 90 | #ifdef NO_FP_API |
82 | /* We should not ever call the default callback routine from | 91 | /* We should not ever call the default callback routine from |
@@ -86,6 +95,12 @@ static int def_callback(char *buf, int num, int w, void *userdata) | |||
86 | #else | 95 | #else |
87 | int i,j; | 96 | int i,j; |
88 | const char *prompt; | 97 | const char *prompt; |
98 | if(key) { | ||
99 | i=strlen(key); | ||
100 | i=(i > num)?num:i; | ||
101 | memcpy(buf,key,i); | ||
102 | return(i); | ||
103 | } | ||
89 | 104 | ||
90 | prompt=EVP_get_pw_prompt(); | 105 | prompt=EVP_get_pw_prompt(); |
91 | if (prompt == NULL) | 106 | if (prompt == NULL) |
@@ -168,6 +183,47 @@ char *PEM_ASN1_read(char *(*d2i)(), const char *name, FILE *fp, char **x, | |||
168 | } | 183 | } |
169 | #endif | 184 | #endif |
170 | 185 | ||
186 | static int check_pem(const char *nm, const char *name) | ||
187 | { | ||
188 | /* Normal matching nm and name */ | ||
189 | if (!strcmp(nm,name)) return 1; | ||
190 | |||
191 | /* Make PEM_STRING_EVP_PKEY match any private key */ | ||
192 | |||
193 | if(!strcmp(nm,PEM_STRING_PKCS8) && | ||
194 | !strcmp(name,PEM_STRING_EVP_PKEY)) return 1; | ||
195 | |||
196 | if(!strcmp(nm,PEM_STRING_PKCS8INF) && | ||
197 | !strcmp(name,PEM_STRING_EVP_PKEY)) return 1; | ||
198 | |||
199 | if(!strcmp(nm,PEM_STRING_RSA) && | ||
200 | !strcmp(name,PEM_STRING_EVP_PKEY)) return 1; | ||
201 | |||
202 | if(!strcmp(nm,PEM_STRING_DSA) && | ||
203 | !strcmp(name,PEM_STRING_EVP_PKEY)) return 1; | ||
204 | |||
205 | /* Permit older strings */ | ||
206 | |||
207 | if(!strcmp(nm,PEM_STRING_X509_OLD) && | ||
208 | !strcmp(name,PEM_STRING_X509)) return 1; | ||
209 | |||
210 | if(!strcmp(nm,PEM_STRING_X509_REQ_OLD) && | ||
211 | !strcmp(name,PEM_STRING_X509_REQ)) return 1; | ||
212 | |||
213 | /* Allow normal certs to be read as trusted certs */ | ||
214 | if(!strcmp(nm,PEM_STRING_X509) && | ||
215 | !strcmp(name,PEM_STRING_X509_TRUSTED)) return 1; | ||
216 | |||
217 | if(!strcmp(nm,PEM_STRING_X509_OLD) && | ||
218 | !strcmp(name,PEM_STRING_X509_TRUSTED)) return 1; | ||
219 | |||
220 | /* Some CAs use PKCS#7 with CERTIFICATE headers */ | ||
221 | if(!strcmp(nm, PEM_STRING_X509) && | ||
222 | !strcmp(name, PEM_STRING_PKCS7)) return 1; | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
171 | char *PEM_ASN1_read_bio(char *(*d2i)(), const char *name, BIO *bp, char **x, | 227 | char *PEM_ASN1_read_bio(char *(*d2i)(), const char *name, BIO *bp, char **x, |
172 | pem_password_cb *cb, void *u) | 228 | pem_password_cb *cb, void *u) |
173 | { | 229 | { |
@@ -179,22 +235,13 @@ char *PEM_ASN1_read_bio(char *(*d2i)(), const char *name, BIO *bp, char **x, | |||
179 | 235 | ||
180 | for (;;) | 236 | for (;;) |
181 | { | 237 | { |
182 | if (!PEM_read_bio(bp,&nm,&header,&data,&len)) return(NULL); | 238 | if (!PEM_read_bio(bp,&nm,&header,&data,&len)) { |
183 | if ( (strcmp(nm,name) == 0) || | 239 | if(ERR_GET_REASON(ERR_peek_error()) == |
184 | ((strcmp(nm,PEM_STRING_RSA) == 0) && | 240 | PEM_R_NO_START_LINE) |
185 | (strcmp(name,PEM_STRING_EVP_PKEY) == 0)) || | 241 | ERR_add_error_data(2, "Expecting: ", name); |
186 | ((strcmp(nm,PEM_STRING_DSA) == 0) && | 242 | return(NULL); |
187 | (strcmp(name,PEM_STRING_EVP_PKEY) == 0)) || | 243 | } |
188 | ((strcmp(nm,PEM_STRING_PKCS8) == 0) && | 244 | if(check_pem(nm, name)) break; |
189 | (strcmp(name,PEM_STRING_EVP_PKEY) == 0)) || | ||
190 | ((strcmp(nm,PEM_STRING_PKCS8INF) == 0) && | ||
191 | (strcmp(name,PEM_STRING_EVP_PKEY) == 0)) || | ||
192 | ((strcmp(nm,PEM_STRING_X509_OLD) == 0) && | ||
193 | (strcmp(name,PEM_STRING_X509) == 0)) || | ||
194 | ((strcmp(nm,PEM_STRING_X509_REQ_OLD) == 0) && | ||
195 | (strcmp(name,PEM_STRING_X509_REQ) == 0)) | ||
196 | ) | ||
197 | break; | ||
198 | Free(nm); | 245 | Free(nm); |
199 | Free(header); | 246 | Free(header); |
200 | Free(data); | 247 | Free(data); |
@@ -218,7 +265,7 @@ char *PEM_ASN1_read_bio(char *(*d2i)(), const char *name, BIO *bp, char **x, | |||
218 | X509_SIG *p8; | 265 | X509_SIG *p8; |
219 | int klen; | 266 | int klen; |
220 | char psbuf[PEM_BUFSIZE]; | 267 | char psbuf[PEM_BUFSIZE]; |
221 | p8 = d2i_X509_SIG((X509_SIG **)x, &p, len); | 268 | p8 = d2i_X509_SIG(NULL, &p, len); |
222 | if(!p8) goto p8err; | 269 | if(!p8) goto p8err; |
223 | if (cb) klen=cb(psbuf,PEM_BUFSIZE,0,u); | 270 | if (cb) klen=cb(psbuf,PEM_BUFSIZE,0,u); |
224 | else klen=def_callback(psbuf,PEM_BUFSIZE,0,u); | 271 | else klen=def_callback(psbuf,PEM_BUFSIZE,0,u); |
@@ -231,6 +278,10 @@ char *PEM_ASN1_read_bio(char *(*d2i)(), const char *name, BIO *bp, char **x, | |||
231 | X509_SIG_free(p8); | 278 | X509_SIG_free(p8); |
232 | if(!p8inf) goto p8err; | 279 | if(!p8inf) goto p8err; |
233 | ret = (char *)EVP_PKCS82PKEY(p8inf); | 280 | ret = (char *)EVP_PKCS82PKEY(p8inf); |
281 | if(x) { | ||
282 | if(*x) EVP_PKEY_free((EVP_PKEY *)*x); | ||
283 | *x = ret; | ||
284 | } | ||
234 | PKCS8_PRIV_KEY_INFO_free(p8inf); | 285 | PKCS8_PRIV_KEY_INFO_free(p8inf); |
235 | } | 286 | } |
236 | } else ret=d2i(x,&p,len); | 287 | } else ret=d2i(x,&p,len); |
@@ -321,8 +372,9 @@ int PEM_ASN1_write_bio(int (*i2d)(), const char *name, BIO *bp, char *x, | |||
321 | #endif | 372 | #endif |
322 | kstr=(unsigned char *)buf; | 373 | kstr=(unsigned char *)buf; |
323 | } | 374 | } |
324 | RAND_seed(data,i);/* put in the RSA key. */ | 375 | RAND_add(data,i,0);/* put in the RSA key. */ |
325 | RAND_bytes(iv,8); /* Generate a salt */ | 376 | if (RAND_bytes(iv,8) <= 0) /* Generate a salt */ |
377 | goto err; | ||
326 | /* The 'iv' is used as the iv and as a salt. It is | 378 | /* The 'iv' is used as the iv and as a salt. It is |
327 | * NOT taken from the BytesToKey function */ | 379 | * NOT taken from the BytesToKey function */ |
328 | EVP_BytesToKey(enc,EVP_md5(),iv,kstr,klen,1,key,NULL); | 380 | EVP_BytesToKey(enc,EVP_md5(),iv,kstr,klen,1,key,NULL); |
@@ -743,16 +795,44 @@ err: | |||
743 | return(0); | 795 | return(0); |
744 | } | 796 | } |
745 | 797 | ||
746 | /* This function writes a private key in PKCS#8 format: it is a "drop in" | 798 | /* These functions write a private key in PKCS#8 format: it is a "drop in" |
747 | * replacement for PEM_write_bio_PrivateKey(). As usual if 'enc' is NULL then | 799 | * replacement for PEM_write_bio_PrivateKey() and friends. As usual if 'enc' |
748 | * it uses the unencrypted private key form. It uses PKCS#5 v2.0 password based | 800 | * is NULL then it uses the unencrypted private key form. The 'nid' versions |
749 | * encryption algorithms. | 801 | * uses PKCS#5 v1.5 PBE algorithms whereas the others use PKCS#5 v2.0. |
750 | */ | 802 | */ |
751 | 803 | ||
804 | int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid, | ||
805 | char *kstr, int klen, | ||
806 | pem_password_cb *cb, void *u) | ||
807 | { | ||
808 | return do_pk8pkey(bp, x, 0, nid, NULL, kstr, klen, cb, u); | ||
809 | } | ||
810 | |||
752 | int PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, | 811 | int PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, |
753 | char *kstr, int klen, | 812 | char *kstr, int klen, |
754 | pem_password_cb *cb, void *u) | 813 | pem_password_cb *cb, void *u) |
755 | { | 814 | { |
815 | return do_pk8pkey(bp, x, 0, -1, enc, kstr, klen, cb, u); | ||
816 | } | ||
817 | |||
818 | int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, | ||
819 | char *kstr, int klen, | ||
820 | pem_password_cb *cb, void *u) | ||
821 | { | ||
822 | return do_pk8pkey(bp, x, 1, -1, enc, kstr, klen, cb, u); | ||
823 | } | ||
824 | |||
825 | int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid, | ||
826 | char *kstr, int klen, | ||
827 | pem_password_cb *cb, void *u) | ||
828 | { | ||
829 | return do_pk8pkey(bp, x, 1, nid, NULL, kstr, klen, cb, u); | ||
830 | } | ||
831 | |||
832 | static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, int nid, const EVP_CIPHER *enc, | ||
833 | char *kstr, int klen, | ||
834 | pem_password_cb *cb, void *u) | ||
835 | { | ||
756 | X509_SIG *p8; | 836 | X509_SIG *p8; |
757 | PKCS8_PRIV_KEY_INFO *p8inf; | 837 | PKCS8_PRIV_KEY_INFO *p8inf; |
758 | char buf[PEM_BUFSIZE]; | 838 | char buf[PEM_BUFSIZE]; |
@@ -762,7 +842,7 @@ int PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, | |||
762 | PEM_R_ERROR_CONVERTING_PRIVATE_KEY); | 842 | PEM_R_ERROR_CONVERTING_PRIVATE_KEY); |
763 | return 0; | 843 | return 0; |
764 | } | 844 | } |
765 | if(enc) { | 845 | if(enc || (nid != -1)) { |
766 | if(!kstr) { | 846 | if(!kstr) { |
767 | if(!cb) klen = def_callback(buf, PEM_BUFSIZE, 1, u); | 847 | if(!cb) klen = def_callback(buf, PEM_BUFSIZE, 1, u); |
768 | else klen = cb(buf, PEM_BUFSIZE, 1, u); | 848 | else klen = cb(buf, PEM_BUFSIZE, 1, u); |
@@ -775,29 +855,109 @@ int PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, | |||
775 | 855 | ||
776 | kstr = buf; | 856 | kstr = buf; |
777 | } | 857 | } |
778 | p8 = PKCS8_encrypt(-1, enc, kstr, klen, NULL, 0, 0, p8inf); | 858 | p8 = PKCS8_encrypt(nid, enc, kstr, klen, NULL, 0, 0, p8inf); |
779 | if(kstr == buf) memset(buf, 0, klen); | 859 | if(kstr == buf) memset(buf, 0, klen); |
780 | PKCS8_PRIV_KEY_INFO_free(p8inf); | 860 | PKCS8_PRIV_KEY_INFO_free(p8inf); |
781 | ret = PEM_write_bio_PKCS8(bp, p8); | 861 | if(isder) ret = i2d_PKCS8_bio(bp, p8); |
862 | else ret = PEM_write_bio_PKCS8(bp, p8); | ||
782 | X509_SIG_free(p8); | 863 | X509_SIG_free(p8); |
783 | return ret; | 864 | return ret; |
784 | } else { | 865 | } else { |
785 | ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf); | 866 | if(isder) ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf); |
867 | else ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf); | ||
786 | PKCS8_PRIV_KEY_INFO_free(p8inf); | 868 | PKCS8_PRIV_KEY_INFO_free(p8inf); |
787 | return ret; | 869 | return ret; |
788 | } | 870 | } |
789 | } | 871 | } |
790 | 872 | ||
873 | /* Finally the DER version to read PKCS#8 encrypted private keys. It has to be | ||
874 | * here to access the default callback. | ||
875 | */ | ||
876 | |||
877 | EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u) | ||
878 | { | ||
879 | PKCS8_PRIV_KEY_INFO *p8inf = NULL; | ||
880 | X509_SIG *p8 = NULL; | ||
881 | int klen; | ||
882 | EVP_PKEY *ret; | ||
883 | char psbuf[PEM_BUFSIZE]; | ||
884 | p8 = d2i_PKCS8_bio(bp, NULL); | ||
885 | if(!p8) return NULL; | ||
886 | if (cb) klen=cb(psbuf,PEM_BUFSIZE,0,u); | ||
887 | else klen=def_callback(psbuf,PEM_BUFSIZE,0,u); | ||
888 | if (klen <= 0) { | ||
889 | PEMerr(PEM_F_D2I_PKCS8PRIVATEKEY_BIO, PEM_R_BAD_PASSWORD_READ); | ||
890 | X509_SIG_free(p8); | ||
891 | return NULL; | ||
892 | } | ||
893 | p8inf = M_PKCS8_decrypt(p8, psbuf, klen); | ||
894 | X509_SIG_free(p8); | ||
895 | if(!p8inf) return NULL; | ||
896 | ret = EVP_PKCS82PKEY(p8inf); | ||
897 | PKCS8_PRIV_KEY_INFO_free(p8inf); | ||
898 | if(!ret) return NULL; | ||
899 | if(x) { | ||
900 | if(*x) EVP_PKEY_free(*x); | ||
901 | *x = ret; | ||
902 | } | ||
903 | return ret; | ||
904 | } | ||
905 | |||
906 | #ifndef NO_FP_API | ||
907 | |||
908 | int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, | ||
909 | char *kstr, int klen, | ||
910 | pem_password_cb *cb, void *u) | ||
911 | { | ||
912 | return do_pk8pkey_fp(fp, x, 1, -1, enc, kstr, klen, cb, u); | ||
913 | } | ||
914 | |||
915 | int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid, | ||
916 | char *kstr, int klen, | ||
917 | pem_password_cb *cb, void *u) | ||
918 | { | ||
919 | return do_pk8pkey_fp(fp, x, 1, nid, NULL, kstr, klen, cb, u); | ||
920 | } | ||
921 | |||
922 | int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid, | ||
923 | char *kstr, int klen, | ||
924 | pem_password_cb *cb, void *u) | ||
925 | { | ||
926 | return do_pk8pkey_fp(fp, x, 0, nid, NULL, kstr, klen, cb, u); | ||
927 | } | ||
928 | |||
791 | int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, | 929 | int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, |
792 | char *kstr, int klen, pem_password_cb *cb, void *u) | 930 | char *kstr, int klen, pem_password_cb *cb, void *u) |
793 | { | 931 | { |
932 | return do_pk8pkey_fp(fp, x, 0, -1, enc, kstr, klen, cb, u); | ||
933 | } | ||
934 | |||
935 | static int do_pk8pkey_fp(FILE *fp, EVP_PKEY *x, int isder, int nid, const EVP_CIPHER *enc, | ||
936 | char *kstr, int klen, | ||
937 | pem_password_cb *cb, void *u) | ||
938 | { | ||
794 | BIO *bp; | 939 | BIO *bp; |
795 | int ret; | 940 | int ret; |
796 | if(!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) { | 941 | if(!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) { |
797 | PEMerr(PEM_F_PEM_F_PEM_WRITE_PKCS8PRIVATEKEY,ERR_R_BUF_LIB); | 942 | PEMerr(PEM_F_PEM_F_DO_PK8KEY_FP,ERR_R_BUF_LIB); |
798 | return(0); | 943 | return(0); |
799 | } | 944 | } |
800 | ret = PEM_write_bio_PKCS8PrivateKey(bp, x, enc, kstr, klen, cb, u); | 945 | ret = do_pk8pkey(bp, x, isder, nid, enc, kstr, klen, cb, u); |
801 | BIO_free(bp); | 946 | BIO_free(bp); |
802 | return ret; | 947 | return ret; |
803 | } | 948 | } |
949 | |||
950 | EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u) | ||
951 | { | ||
952 | BIO *bp; | ||
953 | EVP_PKEY *ret; | ||
954 | if(!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) { | ||
955 | PEMerr(PEM_F_D2I_PKCS8PRIVATEKEY_FP,ERR_R_BUF_LIB); | ||
956 | return NULL; | ||
957 | } | ||
958 | ret = d2i_PKCS8PrivateKey_bio(bp, x, cb, u); | ||
959 | BIO_free(bp); | ||
960 | return ret; | ||
961 | } | ||
962 | |||
963 | #endif | ||