Index: /trunk/doc/manual/en_US/man_VBoxManage-signova.xml
===================================================================
--- /trunk/doc/manual/en_US/man_VBoxManage-signova.xml	(revision 84144)
+++ /trunk/doc/manual/en_US/man_VBoxManage-signova.xml	(revision 84145)
@@ -31,5 +31,5 @@
   <refnamediv>
     <refname>VBoxManage-signova</refname>
-    <refpurpose>move a virtual machine to a new location on the host system</refpurpose>
+    <refpurpose>Digitally sign an OVA</refpurpose>
     <refclass>Oracle VM VirtualBox</refclass>
   </refnamediv>
@@ -98,5 +98,6 @@
         <listitem><para>File containing an intermediary certificate that should be
           included in the optional PKCS#7 signature.  Like the others, the file can
-          either be in PEM or DER format.</para></listitem>
+          either be in PEM or DER format.  This option can be repeated to add
+          multiple intermediate certificates.</para></listitem>
       </varlistentry>
       <varlistentry>
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp	(revision 84144)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp	(revision 84145)
@@ -1790,99 +1790,102 @@
 RTEXITCODE handleSignAppliance(HandlerArg *arg)
 {
-    HRESULT hrc = S_OK;
-
+    /*
+     * Parse arguments.
+     */
     static const RTGETOPTDEF s_aOptions[] =
     {
-        { "--private-key-form",         'k', RTGETOPT_REQ_STRING },
+        { "--certificate",              'c', RTGETOPT_REQ_STRING },
+        { "--private-key",              'k', RTGETOPT_REQ_STRING },
         { "--private-key-password",     'p', RTGETOPT_REQ_STRING },
-        { "--private-key-password-file",'f', RTGETOPT_REQ_STRING },
-        { "--cert-file",                'c', RTGETOPT_REQ_STRING },
+        { "--private-key-password-file",'P', RTGETOPT_REQ_STRING },
+        { "--pkcs7",                    '7', RTGETOPT_REQ_NOTHING },
+        { "--no-pkcs7",                 'n', RTGETOPT_REQ_NOTHING },
         { "--intermediate-cert-file",   'i', RTGETOPT_REQ_STRING },
-        { "--out-cert",                 'o', RTGETOPT_REQ_NOTHING },
-        { "--pkcs7",                    's', RTGETOPT_REQ_NOTHING },
-        { "--no-pkcs7",                 'S', RTGETOPT_REQ_NOTHING },
-        { "--force",                    'F', RTGETOPT_REQ_NOTHING },
-        { "--dry-run",                  'd', RTGETOPT_REQ_NOTHING },
-        { "help",                       1001, RTGETOPT_REQ_NOTHING },
-        { "--help",                     1002, RTGETOPT_REQ_NOTHING }
+        { "--force",                    'f', RTGETOPT_REQ_NOTHING },
+        { "--out-cert",                 'O', RTGETOPT_REQ_NOTHING },
+        { "--dry-run",                  'D', RTGETOPT_REQ_NOTHING },
     };
 
     RTGETOPTSTATE GetState;
-    RTGETOPTUNION ValueUnion;
-
     int rc = RTGetOptInit(&GetState, arg->argc, arg->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
     AssertRCReturn(rc, RTEXITCODE_FAILURE);
-    if (arg->argc == 1)
-    {
-        RTPrintf("Empty command parameter list, show help.\n");
-        printHelp(g_pStdOut);
-        return RTEXITCODE_SUCCESS;
-    }
-
-    Utf8Str strOvfFilename;
-    Utf8Str strPrivateKeyForm;
-    Utf8Str strPrivateKeyPassword;
-    Utf8Str strPrivateKeyPasswordFile;
-    Utf8Str strX509CertificateFile;
-    Utf8Str strInterimCertificateFile;
-    bool    fOutCert = false; // the default
-    bool    fPKCS7 = false; // the default
-    bool    fResign = false; // the default
-    bool    fDry = false; // the default
-    com::SafeArray<BSTR>  parameters;
+
+    const char *pszOva              = NULL;
+    const char *pszCertificate      = NULL;
+    const char *pszPrivateKey       = NULL;
+    Utf8Str     strPrivateKeyPassword;
+    bool        fPkcs7              = false;
+    unsigned    cIntermediateCerts  = 0;
+    const char *apszIntermediateCerts[32];
+    bool        fReSign             = false;
+
+    bool        fOutCert            = false;
+    bool        fDryRun             = false;
 
     int c;
+    RTGETOPTUNION ValueUnion;
     while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
     {
         switch (c)
         {
+            case 'c':
+                pszCertificate = ValueUnion.psz;
+                break;
+
             case 'k':
-                strPrivateKeyForm=ValueUnion.psz;
+                pszPrivateKey = ValueUnion.psz;
                 break;
 
             case 'p':
-                strPrivateKeyPassword=ValueUnion.psz;
+                if (strPrivateKeyPassword.isNotEmpty())
+                    RTMsgWarning("Password is given more than once.");
+                strPrivateKeyPassword = ValueUnion.psz;
+                break;
+
+            case 'P':
+            {
+                if (strPrivateKeyPassword.isNotEmpty())
+                    RTMsgWarning("Password is given more than once.");
+                RTEXITCODE rcExit = readPasswordFile(ValueUnion.psz, &strPrivateKeyPassword);
+                if (rcExit == RTEXITCODE_SUCCESS)
+                    break;
+                return rcExit;
+            }
+
+            case '7':
+                fPkcs7 = true;
+                break;
+
+            case 'n':
+                fPkcs7 = false;
+                break;
+
+            case 'i':
+                if (cIntermediateCerts >= RT_ELEMENTS(apszIntermediateCerts))
+                    return RTMsgErrorExitFailure("Too many intermediate certificates: max %zu",
+                                                 RT_ELEMENTS(apszIntermediateCerts));
+                apszIntermediateCerts[cIntermediateCerts++] = ValueUnion.psz;
                 break;
 
             case 'f':
-                strPrivateKeyPasswordFile=ValueUnion.psz;
-                break;
-
-            case 'c':
-                strX509CertificateFile=ValueUnion.psz;
-                break;
-
-            case 'i':
-                strInterimCertificateFile=ValueUnion.psz;
-                break;
-
-            case 'o':
+                fReSign = true;
+                break;
+
+
+            case 'O':
                 fOutCert = true;
                 break;
 
-            case 's':
-                fPKCS7 = true;
-                break;
-
-            case 'F':
-                fResign = true;
-                break;
-
-            case 'd':
-                fDry = true;
-                break;
-
-            case 1001:
-            case 1002:
-                printHelp(g_pStdOut);
-                return RTEXITCODE_SUCCESS;
+            case 'D':
+                fDryRun = true;
+                break;
 
             case VINF_GETOPT_NOT_OPTION:
-                if (strOvfFilename.isEmpty())
-                    strOvfFilename = ValueUnion.psz;
-                else
-                    return errorGetOpt(c, &ValueUnion);
-                break;
-
+                if (!pszOva)
+                {
+                    pszOva = ValueUnion.psz;
+                    break;
+                }
+                RT_FALL_THRU();
             default:
                 return errorGetOpt(c, &ValueUnion);
@@ -1890,4 +1893,25 @@
     }
 
+    /* Required paramaters: */
+    if (!pszOva || !*pszOva)
+        return RTMsgErrorExit(RTEXITCODE_FAILURE, "No OVA file was specified!");
+    if (!pszCertificate || !*pszCertificate)
+        return RTMsgErrorExit(RTEXITCODE_FAILURE, "No signing certificate (--certificate=<file>) was specified!");
+    if (!pszPrivateKey || !*pszPrivateKey)
+        return RTMsgErrorExit(RTEXITCODE_FAILURE, "No signing private key (--private-key=<file>) was specified!");
+
+    /* Check that input files exists before we commence: */
+    if (!RTFileExists(pszOva))
+        return RTMsgErrorExit(RTEXITCODE_FAILURE, "The specified OVA file was not found: %s", pszOva);
+    if (!RTFileExists(pszCertificate))
+        return RTMsgErrorExit(RTEXITCODE_FAILURE, "The specified certificate file was not found: %s", pszCertificate);
+    if (!RTFileExists(pszPrivateKey))
+        return RTMsgErrorExit(RTEXITCODE_FAILURE, "The specified private key file was not found: %s", pszPrivateKey);
+
+    /*
+     *
+     */
+    HRESULT hrc = S_OK;
+
     Utf8Str strManifestData;
     Utf8Str strManifestName;
@@ -1895,10 +1919,8 @@
     Utf8Str strApplianceFullPath;
 
-    if (strOvfFilename.isEmpty())
-        return RTMsgErrorExit(RTEXITCODE_FAILURE, "The OVA package name is empty");
+    char *pszAbsFilePath = RTPathAbsDup(pszOva);
 
     do
     {
-        char *pszAbsFilePath = RTPathAbsDup(strOvfFilename.c_str());
 
         if (!RTFileExists(pszAbsFilePath))
@@ -1946,41 +1968,24 @@
 
     /* Read the private key */
-    RTCRKEY hPrivateKey;
-    RTERRINFO ErrInfo;
-    uint32_t fFlags = 0;
-
-    if (strPrivateKeyForm.equalsIgnoreCase("pem"))
-        fFlags = RTCRPEMREADFILE_F_VALID_MASK;//|RTCRKEYFROM_F_VALID_MASK;
-
-    /* check the key file existence */
-    if (!RTFileExists(strPrivateKeyPasswordFile.c_str()))
-        return RTMsgErrorExit(RTEXITCODE_FAILURE, "The file %s with a private key wasn't found",
-                              strPrivateKeyPasswordFile.c_str());
-
-    rc = RTCrKeyCreateFromFile(&hPrivateKey, 0, strPrivateKeyPasswordFile.c_str(), strPrivateKeyPassword.c_str(), &ErrInfo);
+    RTERRINFOSTATIC ErrInfo;
+    RTCRKEY         hPrivateKey = NIL_RTCRKEY;
+    rc = RTCrKeyCreateFromFile(&hPrivateKey, RTCRPEMREADFILE_F_SENSITIVE, pszPrivateKey,
+                               strPrivateKeyPassword.c_str(), RTErrInfoInitStatic(&ErrInfo));
     if (RT_SUCCESS(rc))
     {
-        RTPrintf("Reading the private key from %s was done.\n\n", strPrivateKeyPasswordFile.c_str());
-
-        /* check the certificate file existence */
-        if (!RTFileExists(strX509CertificateFile.c_str()))
-        {
-            RTCrKeyRelease(hPrivateKey);
-            return RTMsgErrorExit(RTEXITCODE_FAILURE, "The file %s with a X509 certificate wasn't found",
-                                  strX509CertificateFile.c_str());
-        }
+        RTPrintf("Reading the private key from %s was done.\n\n", pszPrivateKey);
 
         /* Read the certificate */
         RTCRX509CERTIFICATE     Certificate;
-        rc = RTCrX509Certificate_ReadFromFile(&Certificate, strX509CertificateFile.c_str(), 0, &g_RTAsn1DefaultAllocator,
-                                              &ErrInfo);
+        rc = RTCrX509Certificate_ReadFromFile(&Certificate, pszCertificate, 0, &g_RTAsn1DefaultAllocator,
+                                              RTErrInfoInitStatic(&ErrInfo));
         if (RT_FAILURE(rc))
         {
             RTCrKeyRelease(hPrivateKey);
-            return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error reading certificate from %s: %Rrc - %s",
-                                  strX509CertificateFile.c_str(), rc, ErrInfo.pszMsg);
+            return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error reading certificate from %s: %Rrc%#RTeim",
+                                  pszCertificate, rc, &ErrInfo.Core);
         }
 
-        RTPrintf("Reading the certificate from %s was done.\n\n", strX509CertificateFile.c_str());
+        RTPrintf("Reading the certificate from %s was done.\n\n", pszCertificate);
 
         /*
@@ -2026,5 +2031,5 @@
                                               signatureBuf,
                                               &cbSignature,
-                                              &ErrInfo);
+                                              RTErrInfoInitStatic(&ErrInfo));
                 if (RT_SUCCESS(rc))
                 {
@@ -2034,5 +2039,6 @@
                     /* Verify the signature back using the public key information from the certificate */
                     rc = RTCrPkixPubKeyVerifySignedDigestByCertPubKeyInfo(&Certificate.TbsCertificate.SubjectPublicKeyInfo,
-                                                                          signatureBuf, cbSignature, hDigest, &ErrInfo);
+                                                                          signatureBuf, cbSignature, hDigest,
+                                                                          RTErrInfoInitStatic(&ErrInfo));
                     if (RT_FAILURE(rc))
                     {
@@ -2043,9 +2049,8 @@
                             return RTMsgErrorExit(RTEXITCODE_FAILURE, "The manifest signature does not match");
 
-                        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error validating the manifest signature (%Rrc, %s)",
-                                              rc, ErrInfo.pszMsg);
+                        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error validating the manifest signature (%Rrc%#RTeim)",
+                                              rc, &ErrInfo.Core);
                     }
-                    else
-                        RTPrintf("The manifest signature was validated successfully\n\n");
+                    RTPrintf("The manifest signature was validated successfully\n\n");
 
                     /*
@@ -2078,5 +2083,5 @@
 
                     /* Just stop here in the case of dry-run scenario */
-                    if (fDry)
+                    if (fDryRun)
                     {
                         /* Dont' forget */
@@ -2105,6 +2110,5 @@
                             /* Open and read the passed certificate file as a standard file */
                             RTVFSFILE     hVfsOriginalX509Certificate;
-                            rc = RTVfsFileOpenNormal(strX509CertificateFile.c_str(),
-                                                     RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE,
+                            rc = RTVfsFileOpenNormal(pszCertificate, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE,
                                                      &hVfsOriginalX509Certificate);
                             if (RT_SUCCESS(rc))
@@ -2127,6 +2131,5 @@
                             }
                             else
-                                RTPrintf("Reading the certificate from the file %s failed (%Rrc)",
-                                         strX509CertificateFile.c_str(), rc);
+                                RTPrintf("Reading the certificate from the file %s failed (%Rrc)", pszCertificate, rc);
 
                             /* Dont' forget */
@@ -2144,6 +2147,5 @@
                             }
                             else
-                                RTPrintf("Reading the certificate from the file %s failed (%Rrc)",
-                                         strX509CertificateFile.c_str(), rc);
+                                RTPrintf("Reading the certificate from the file %s failed (%Rrc)", pszCertificate, rc);
                         }
                         else
@@ -2231,5 +2233,5 @@
                                             fCertPresence = true;//remember for later usage
                                             /* if the flag --force has been set just skip it and go further */
-                                            if (fResign)
+                                            if (fReSign)
                                                 continue;
                                         }
@@ -2266,6 +2268,6 @@
                             if (RT_SUCCESS(rc))
                             {
-                                /* Add only if no cetificate or the flag fResign was set and certificate is presented */
-                                if ( !fCertPresence || (fCertPresence && fResign) )
+                                /* Add only if no cetificate or the flag fReSign was set and certificate is presented */
+                                if ( !fCertPresence || (fCertPresence && fReSign) )
                                 {
                                     size_t cbWritten;
@@ -2367,5 +2369,5 @@
     }
     else
-        RTPrintf("Error reading the private key from %s: %Rrc - %s", strPrivateKeyPasswordFile.c_str(), rc, ErrInfo.pszMsg);
+        RTPrintf("Error reading the private key from %s: %Rrc%#RTeim", pszPrivateKey, rc, &ErrInfo.Core);
 
     /* Dont' forget */
