Fixes for writing 3D CPLs.
[libdcp.git] / src / crypt_chain.cc
1 /*
2     Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <fstream>
21 #include <sstream>
22 #include <boost/filesystem.hpp>
23 #include <boost/algorithm/string.hpp>
24 #include "crypt_chain.h"
25 #include "exceptions.h"
26
27 using std::string;
28 using std::ofstream;
29 using std::ifstream;
30 using std::stringstream;
31 using std::cout;
32
33 static void command (char const * c)
34 {
35         int const r = system (c);
36 #ifdef LIBDCP_WINDOWS   
37         if (r) {
38 #else
39         if (WEXITSTATUS (r)) {
40 #endif          
41                 stringstream s;
42                 s << "error in " << c << "\n";
43                 throw libdcp::MiscError (s.str());
44         }
45 }
46
47 void
48 libdcp::make_crypt_chain (boost::filesystem::path directory)
49 {
50         boost::filesystem::current_path (directory);
51         command ("openssl genrsa -out ca.key 2048");
52
53         {
54                 ofstream f ("ca.cnf");
55                 f << "[ req ]\n"
56                   << "distinguished_name = req_distinguished_name\n"
57                   << "x509_extensions   = v3_ca\n"
58                   << "[ v3_ca ]\n"
59                   << "basicConstraints = critical,CA:true,pathlen:3\n"
60                   << "keyUsage = keyCertSign,cRLSign\n"
61                   << "subjectKeyIdentifier = hash\n"
62                   << "authorityKeyIdentifier = keyid:always,issuer:always\n"
63                   << "[ req_distinguished_name ]\n"
64                   << "O = Unique organization name\n"
65                   << "OU = Organization unit\n"
66                   << "CN = Entity and dnQualifier\n";
67         }
68
69         command ("openssl rsa -outform PEM -pubout -in ca.key | openssl base64 -d | dd bs=1 skip=24 2>/dev/null | openssl sha1 -binary | openssl base64 > ca_dnq");
70
71         string ca_dnq;
72
73         {
74                 ifstream f ("ca_dnq");
75                 getline (f, ca_dnq);
76                 /* XXX: is this right? */
77                 boost::replace_all (ca_dnq, "/", "\\\\/");
78         }
79         
80         string const ca_subject = "/O=example.org/OU=example.org/CN=.smpte-430-2.ROOT.NOT_FOR_PRODUCTION/dnQualifier=" + ca_dnq;
81
82         {
83                 stringstream c;
84                 c << "openssl req -new -x509 -sha256 -config ca.cnf -days 3650 -set_serial 5 -subj " << ca_subject << " -key ca.key -outform PEM -out ca.self-signed.pem";
85                 command (c.str().c_str());
86         }
87
88         command ("openssl genrsa -out intermediate.key 2048");
89
90         {
91                 ofstream f ("intermediate.cnf");
92                 f << "[ default ]\n"
93                   << "distinguished_name = req_distinguished_name\n"
94                   << "x509_extensions = v3_ca\n"
95                   << "[ v3_ca ]\n"
96                   << "basicConstraints = critical,CA:true,pathlen:2\n"
97                   << "keyUsage = keyCertSign,cRLSign\n"
98                   << "subjectKeyIdentifier = hash\n"
99                   << "authorityKeyIdentifier = keyid:always,issuer:always\n"
100                   << "[ req_distinguished_name ]\n"
101                   << "O = Unique organization name\n"
102                   << "OU = Organization unit\n"
103                   << "CN = Entity and dnQualifier\n";
104         }
105
106         command ("openssl rsa -outform PEM -pubout -in intermediate.key | openssl base64 -d | dd bs=1 skip=24 2>/dev/null | openssl sha1 -binary | openssl base64 > inter_dnq");
107         
108         string inter_dnq;
109
110         {
111                 ifstream f ("inter_dnq");
112                 getline (f, inter_dnq);
113                 boost::replace_all (inter_dnq, "/", "\\\\/");
114         }
115                 
116         string const inter_subject = "/O=example.org/OU=example.org/CN=.smpte-430-2.INTERMEDIATE.NOT_FOR_PRODUCTION/dnQualifier=" + inter_dnq;
117
118         {
119                 stringstream s;
120                 s << "openssl req -new -config intermediate.cnf -days 3649 -subj " << inter_subject << " -key intermediate.key -out intermediate.csr";
121                 command (s.str().c_str());
122         }
123
124         
125         command ("openssl x509 -req -sha256 -days 3649 -CA ca.self-signed.pem -CAkey ca.key -set_serial 6 -in intermediate.csr -extfile intermediate.cnf -extensions v3_ca -out intermediate.signed.pem");
126
127         command ("openssl genrsa -out leaf.key 2048");
128
129         {
130                 ofstream f ("leaf.cnf");
131                 f << "[ default ]\n"
132                   << "distinguished_name = req_distinguished_name\n"
133                   << "x509_extensions   = v3_ca\n"
134                   << "[ v3_ca ]\n"
135                   << "basicConstraints = critical,CA:false\n"
136                   << "keyUsage = digitalSignature,keyEncipherment\n"
137                   << "subjectKeyIdentifier = hash\n"
138                   << "authorityKeyIdentifier = keyid,issuer:always\n"
139                   << "[ req_distinguished_name ]\n"
140                   << "O = Unique organization name\n"
141                   << "OU = Organization unit\n"
142                   << "CN = Entity and dnQualifier\n";
143         }
144
145         command ("openssl rsa -outform PEM -pubout -in leaf.key | openssl base64 -d | dd bs=1 skip=24 2>/dev/null | openssl sha1 -binary | openssl base64 > leaf_dnq");
146         
147         string leaf_dnq;
148
149         {
150                 ifstream f ("leaf_dnq");
151                 getline (f, leaf_dnq);
152                 boost::replace_all (leaf_dnq, "/", "\\\\/");
153         }
154
155         string const leaf_subject = "/O=example.org/OU=example.org/CN=CS.smpte-430-2.LEAF.NOT_FOR_PRODUCTION/dnQualifier=" + leaf_dnq;
156
157         {
158                 stringstream s;
159                 s << "openssl req -new -config leaf.cnf -days 3648 -subj " << leaf_subject << " -key leaf.key -outform PEM -out leaf.csr";
160                 command (s.str().c_str());
161         }
162
163         command ("openssl x509 -req -sha256 -days 3648 -CA intermediate.signed.pem -CAkey intermediate.key -set_serial 7 -in leaf.csr -extfile leaf.cnf -extensions v3_ca -out leaf.signed.pem");
164 }